Problem Description
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.

 
Input
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.

 
Output
For each test case, output the maximum number of edges Soda can add.
 
Sample Input
2
4 2
1 2
2 3
4 4
1 2
1 4
2 3
3 4
 
Sample Output
2
0
 
Source

 题意:给定一个二分图,要求添加最多的边将原来的二分图变成完全二分图。

解法一:dfs染色:

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

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define N 10006
int n,m;
vector<int>G[N];
int color[N];
int ans[];
void init()
{
for(int i=;i<=n;i++)
{
G[i].clear();
color[i]=-;
}
ans[]=ans[]=; }
void dfs(int cur,int cnt)
{
for(int i=;i<G[cur].size();i++)
{
int u=G[cur][i];
if(color[u]==-)
{
color[u]=;
ans[cnt]++;
dfs(u,cnt^);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=;i<=n;i++)
{
if(color[i]==- && G[i].size()!=)
{
color[i]=;
ans[]++;
dfs(i,);
}
} int res=; for(int i=;i<=n;i++)
{
if(color[i]==-)
res++;
} while(res--)
{
if(ans[]<ans[])
ans[]++;
else
ans[]++;
}
printf("%d\n",ans[]*ans[]-m);
} return ;
}

解法二:并查集

dis数组用来记录各个点的状态,即记录点是加入左边还是右边。其他的基本相同。

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 10006
int n,m;
int vis[N];
int fa[N];
int dis[N];
void init()
{
for(int i=;i<=n;i++)
{
fa[i]=i;
vis[i]=dis[i]=;
}
}
int find(int x)
{
if(x!=fa[x])
{
int t=find(fa[x]);
dis[x]=(dis[x]+dis[fa[x]])&;
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]+)&;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
merge(x,y);
vis[x]=vis[y]=;
} //int cnt=x=y=0;
int cnt=;
int x=;
int y=;
for(int i=;i<=n;i++)
find(i);
for(int i=;i<=n;i++)
{
if(vis[i]) if(dis[i]&) x++; else y++;
else cnt++;
}
while(cnt--)
{
if(x<y)
x++;
else
y++;
}
printf("%d\n",x*y-m); }
return ;
}

hdu 5313 Bipartite Graph(dfs染色 或者 并查集)的更多相关文章

  1. HDU 5313 Bipartite Graph(二分图染色+01背包水过)

    Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants ...

  2. HDU 5313——Bipartite Graph——————【二分图+dp+bitset优化】

    Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  3. HDU 5313 Bipartite Graph

    题意:给一个二分图,问想让二分图变成完全二分图最多能加多少条边. 解法:图染色+dp+bitset优化.设最终的完全二分图两部分点集为A和B,A中点个数为x,B中点个数为y,边数则为x × y,答案即 ...

  4. HDU 5313 Bipartite Graph (二分图着色,dp)

    题意: Soda有一个n个点m条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的. 思路: 先将二分图着色,将每个连通分 ...

  5. BZOJ_2303_[Apio2011]方格染色 _并查集

    BZOJ_2303_[Apio2011]方格染色 _并查集 Description Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好, ...

  6. P1141 01迷宫 DFS (用并查集优化)

    题目描述 有一个仅由数字00与11组成的n \times nn×n格迷宫.若你位于一格0上,那么你可以移动到相邻44格中的某一格11上,同样若你位于一格1上,那么你可以移动到相邻44格中的某一格00上 ...

  7. hdu 4751 Divide Groups(dfs染色 或 2-sat)

    Problem Description   This year is the 60th anniversary of NJUST, and to make the celebration more c ...

  8. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  9. HDU 5285 wyh2000 and pupil(dfs或种类并查集)

    wyh2000 and pupil Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Other ...

随机推荐

  1. Dynamics CRM记录页面上隐藏子网格“+”标识

    前段时间微软发布了Dynamics 365,这是Dynamics产品的又一次大的变动,期待新的版本能够更好的满足客户的需求,同时提供更多的可定制化的内容. 近期做Dynamics CRM项目遇到很多审 ...

  2. Linux的VI/VIM

    参考自:http://www.cnblogs.com/itech/archive/2009/04/17/1438439.html 作者:iTech 出处:http://itech.cnblogs.co ...

  3. OD: Heap Exploit : DWORD Shooting & Opcode Injecting

    堆块分配时的任意地址写入攻击原理 堆管理系统的三类操作:分配.释放.合并,归根到底都是对堆块链表的修改.如果能伪造链表结点的指针,那么在链表装卸的过程中就有可能获得读写内存的机会.堆溢出利用的精髓就是 ...

  4. java listener实现定时任务

    使用java ServletContextListener 实现各种简单定时任务. 1. 创建ServletContextListener,在3.0版本的web.xml中不再需要添加listener的 ...

  5. AngularJs练习Demo16 ngRoute

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. WdatePicker 设置今天起 后30天可选

    <link href="{:ADDON_PUBLIC_PATH}/style/My97DatePicker/skin/WdatePicker.css" rel="s ...

  7. java比较器Comparator 使用

    PresonDemo package cn.stat.p5.person.demo; public class PresonDemo implements Comparable { private S ...

  8. java 后台线层也叫守护线层

    import java.util.concurrent.locks.*; class Do9 { public static void main(String[] args) { Ds d=new D ...

  9. MFC 点击改变文本 加法计时器 伸缩窗体

    1.添加所需控件,设置ID:labNum1,txtNum1.txtNum2.txtNum3.btnAdd,并将labNum1的属性Notify->true(控件在被单击或双击时可以发送消息) 2 ...

  10. IIS中启用gzip压缩(网站优化)

    HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术.大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度.这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的 ...