标签:
题意:给定一个二分图,要求添加最多的边将原来的二分图变成完全二分图。
解法一:dfs染色:
ans[0]表示左边的图的点个数, ans[1]表示右边的点个数,跑一个dfs,将给定二分图分成两种颜色(color数组用来记录是否染色到),然后没有染色到的就加入左右两边,使得左右两边尽可能接近,相乘 再减掉原来给定边的数量就是能加得最多的边数了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<set> 6 #include<map> 7 using namespace std; 8 #define N 10006 9 int n,m; 10 vector<int>G[N]; 11 int color[N]; 12 int ans[2]; 13 void init() 14 { 15 for(int i=0;i<=n;i++) 16 { 17 G[i].clear(); 18 color[i]=-1; 19 } 20 ans[0]=ans[1]=0; 21 22 } 23 void dfs(int cur,int cnt) 24 { 25 for(int i=0;i<G[cur].size();i++) 26 { 27 int u=G[cur][i]; 28 if(color[u]==-1) 29 { 30 color[u]=0; 31 ans[cnt]++; 32 dfs(u,cnt^1); 33 } 34 } 35 } 36 int main() 37 { 38 int t; 39 scanf("%d",&t); 40 while(t--) 41 { 42 scanf("%d%d",&n,&m); 43 init(); 44 for(int i=0;i<m;i++) 45 { 46 int x,y; 47 scanf("%d%d",&x,&y); 48 G[x].push_back(y); 49 G[y].push_back(x); 50 } 51 for(int i=1;i<=n;i++) 52 { 53 if(color[i]==-1 && G[i].size()!=0) 54 { 55 color[i]=0; 56 ans[0]++; 57 dfs(i,1); 58 } 59 } 60 61 int res=0; 62 63 for(int i=1;i<=n;i++) 64 { 65 if(color[i]==-1) 66 res++; 67 } 68 69 while(res--) 70 { 71 if(ans[0]<ans[1]) 72 ans[0]++; 73 else 74 ans[1]++; 75 } 76 printf("%d\n",ans[0]*ans[1]-m); 77 } 78 79 return 0; 80 }
解法二:并查集
dis数组用来记录各个点的状态,即记录点是加入左边还是右边。其他的基本相同。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N 10006 6 int n,m; 7 int vis[N]; 8 int fa[N]; 9 int dis[N]; 10 void init() 11 { 12 for(int i=0;i<=n;i++) 13 { 14 fa[i]=i; 15 vis[i]=dis[i]=0; 16 } 17 } 18 int find(int x) 19 { 20 if(x!=fa[x]) 21 { 22 int t=find(fa[x]); 23 dis[x]=(dis[x]+dis[fa[x]])&1; 24 fa[x]=t; 25 } 26 return fa[x]; 27 } 28 void merge(int x,int y) 29 { 30 int root1=find(x); 31 int root2=find(y); 32 if(root1==root2) return; 33 fa[root1]=root2; 34 dis[root1]=(dis[x]+dis[y]+1)&1; 35 } 36 int main() 37 { 38 int t; 39 scanf("%d",&t); 40 while(t--) 41 { 42 scanf("%d%d",&n,&m); 43 init(); 44 for(int i=0;i<m;i++) 45 { 46 int x,y; 47 scanf("%d%d",&x,&y); 48 merge(x,y); 49 vis[x]=vis[y]=1; 50 } 51 52 //int cnt=x=y=0; 53 int cnt=0; 54 int x=0; 55 int y=0; 56 for(int i=1;i<=n;i++) 57 find(i); 58 for(int i=1;i<=n;i++) 59 { 60 if(vis[i]) if(dis[i]&1) x++; else y++; 61 else cnt++; 62 } 63 while(cnt--) 64 { 65 if(x<y) 66 x++; 67 else 68 y++; 69 } 70 printf("%d\n",x*y-m); 71 72 } 73 return 0; 74 }
hdu 5313 Bipartite Graph(dfs染色 或者 并查集)
标签:
原文地址:http://www.cnblogs.com/UniqueColor/p/4732879.html