【题意】中文点击这里
【分析】这题比赛的时候想着贪心(差值排序,大的往小的填),然后其实是错的,下面这组数据就可以卡掉(ans=229)。然后到现在为止,很多这样的做的都AC了,看来数据比较弱.现在BC上那AC的93份代码,我随便测了几个大部分都是错的,唉,希望会再加一次数据。
1 32 27 1 2 1 3 1 4 1 5 1 6 1 7 1 8 9 10 9 11 9 12 9 13 9 14 9 15 16 17 16 18 16 19 16 20 16 21 22 23 22 24 22 25 22 26 22 27 28 29 28 30 28 31 28 32
其实是DP,用dp[i][k]表示前i组能否使一边取到,dp方程也容易想到:dp[i][k] = max(dp[i-1][k-a[i]]||dp[i-1][k-b[i]]),但是直接DP是n^2的,容易超时(据说加优化可以不超时,我不会优化),可以用bitset来优化,这样就能过了。
【AC CODE】483ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 10000+10, MAXM = 100000*2+10; char buf[MAXM], *ps = buf, *pe = buf+1; inline void rnext(){ if(++ps == pe) pe = (ps = buf)+fread(buf,1,sizeof(buf),stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; do{ rnext(); if('-' == *ps) f = -1; }while(!isdigit(*ps) && ps != pe); if(ps == pe) return false;//EOF do { ans = (ans<<1)+(ans<<3)+*ps-48; rnext(); }while(isdigit(*ps) && ps != pe); ans *= f; return true; } int head[MAXN], tol,nxt[MAXM],to[MAXM]; int col[MAXN]; void add_edge(int u, int v) { nxt[tol] = head[u], to[tol] = v; head[u] = tol++; } int cnt[2]; void dfs(int u, int c) { col[u] = c; cnt[c]++; for(int i = head[u]; ~i; i = nxt[i]) { int v = to[i]; if(-1 == col[v]) dfs(v,c^1); } } int n,m,a[MAXN],b[MAXN]; bool dp[MAXN]; int sloved() { int block = 0,mx = 0; clc(col,-1); repe(i,1,n) { if(~col[i]) continue; clc(cnt,0); dfs(i,0); a[++block] = cnt[0],b[block] = cnt[1]; mx += max(cnt[0],cnt[1]); } clc(dp,0); dp[0] = 1; repe(i,1,block) { repe(j,1,mx) { dp[j] = dp[j-a[i]]||dp[j-b[i]]; } } int ans = 0; repe(i,1,mx) { if(dp[i]) ans = max(ans,i*(n-i)); } return ans-m; } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int t; in(t); while(t--) { in(n),in(m); clc(head,-1); tol = 0; repe(i,1,m) { int u,v; in(u),in(v); add_edge(u,v); add_edge(v,u); } printf("%d\n", sloved()); } return 0; }