您的位置:首页 > 其它

hdu 5313 Bipartite Graph(dfs染色 或者 并查集)

2015-08-15 18:03 281 查看
[align=left]Problem Description[/align]
Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges he can add.

Note: There must be at most one edge between any pair of vertices both in the new graph and old graph.

[align=left]Input[/align]
There are multiple test cases. The first line of input contains an integer T (1≤T≤100), indicating the number of test cases. For each test case:

The first line contains two integers n and m, (2≤n≤10000,0≤m≤100000).

Each of the next m lines contains two integer u,v (1≤u,v≤n,v≠u) which means there's an undirected edge between vertex u and vertex v.

There's at most one edge between any pair of vertices. Most test cases are small.

[align=left]Output[/align]
For each test case, output the maximum number of edges Soda can add.

[align=left]Sample Input[/align]

2
4 2
1 2
2 3
4 4
1 2
1 4
2 3
3 4

[align=left]Sample Output[/align]

2
0

[align=left]Source[/align]
BestCoder 1st Anniversary ($)
题意:给定一个二分图,要求添加最多的边将原来的二分图变成完全二分图。

解法一:dfs染色:

ans[0]表示左边的图的点个数, ans[1]表示右边的点个数,跑一个dfs,将给定二分图分成两种颜色(color数组用来记录是否染色到),然后没有染色到的就加入左右两边,使得左右两边尽可能接近,相乘 再减掉原来给定边的数量就是能加得最多的边数了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 10006
int n,m;
int vis
;
int fa
;
int dis
;
void init()
{
for(int i=0;i<=n;i++)
{
fa[i]=i;
vis[i]=dis[i]=0;
}
}
int find(int x)
{
if(x!=fa[x])
{
int t=find(fa[x]);
dis[x]=(dis[x]+dis[fa[x]])&1;
fa[x]=t;
}
return fa[x];
}
void merge(int x,int y)
{
int root1=find(x);
int root2=find(y);
if(root1==root2) return;
fa[root1]=root2;
dis[root1]=(dis[x]+dis[y]+1)&1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
merge(x,y);
vis[x]=vis[y]=1;
}

//int cnt=x=y=0;
int cnt=0;
int x=0;
int y=0;
for(int i=1;i<=n;i++)
find(i);
for(int i=1;i<=n;i++)
{
if(vis[i]) if(dis[i]&1) x++; else y++;
else cnt++;
}
while(cnt--)
{
if(x<y)
x++;
else
y++;
}
printf("%d\n",x*y-m);

}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: