1. 程式人生 > 實用技巧 >AtCoder Regular Contest 099 E - Independence

AtCoder Regular Contest 099 E - Independence

題意

給你一個無向圖 不會有重邊和自環

然後要求你把所有點分成兩個集合,每個集合的點必須是個完全圖,

如果滿足不了上述條件 輸出-1;

題解:
考慮建原圖的補圖;

即,若兩點之間沒有邊,則連邊;

若這個圖不是二分圖,那麼無解,感性理解一下就行了

注意你雖然是二分圖,但是不一定是全聯通,可能是很多個連通二分圖組成

然後二分圖的各個連通塊染色一下,統計左右兩邊的數目,

最後o(n)的取一下最小值就行了

然後這個題細節很多,學到了很多細節,建議學習一下程式碼

#include <bits/stdc++.h>
using namespace std;
const int N=2005;
int
n,m; int g[N][N]; int dp[N],e[N],vis[N],x,y,f=0; void dfs(int p,int t){ if (vis[p]){ if (vis[p]!=t+1) f=1; return; } vis[p]=t+1; if (t) x++; else y++; for (int i=1;i<=n;i++) if (i!=p&&!g[p][i]) dfs(i,t
^1); } int calc(int x){ return x*(x-1)/2; } int main(){ scanf("%d%d",&n,&m); for (int i=1,a,b;i<=m;i++){ scanf("%d%d",&a,&b); g[a][b]=g[b][a]=1; } memset(dp,0,sizeof dp); dp[0]=1; for (int i=1;i<=n;i++){ if (vis[i]) continue
; x=0,y=0; dfs(i,0); memset(e,0,sizeof e); for (int j=n;j>=0;j--) //注意這個地方的技巧,統計數目答案 e[j+x]|=dp[j],e[j+y]|=dp[j]; for (int j=0;j<=n;j++) dp[j]=e[j]; } if (f){ puts("-1"); return 0; } int ans=n*n*2; for (int i=0;i<=n;i++) if (dp[i])//如果出現過,計算一下 ans=min(ans,calc(i)+calc(n-i)); printf("%d",ans); return 0; }