HDU 2444 The Accomodation of Students(二分图判定+最大匹配)
2014-08-18 14:55
591 查看
HDU 2444 The Accomodation of Students(二分图判定+最大匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:
给你N个学生与M对关系,每个关系形如(i,j),表示第i个学生与第j个学生相互认识. 现在要你将N个学生分成两组,每组中的任意两个学生都不相互认识.
如果N个学生能分组的话,那么就将这N个学生放到尽量多的双人房中去.每个房间放2个相互认识的人.问你最多需要多少房间?
分析:
首先第一步将N个学生分成两类就是看能否将图二分.假设每个学生是一个节点,如果i学生与j学生认识,那么i点和j点之间连一条无向边. 然后我们将图分成两部分,左边部分和右边部分.且各部分内部不存在边,所有边一定是左边与右边点之间的边.(这就是二分图的定义)
判断二分图的话直接用刘汝佳的模板即可.
如果该图能二分, 直观的做法是将所有点重新编号分成左右两边.然后再计算最大匹配. 但是给点重新编号明显比较麻烦,这里我们将原图翻倍处理,然后直接计算出翻倍后图的最大匹配数X. 最终X/2就是我们所求.
翻倍原图具体原理证明在POJ1466:
/article/1517373.html
AC代码:
http://acm.hdu.edu.cn/showproblem.php?pid=2444
题意:
给你N个学生与M对关系,每个关系形如(i,j),表示第i个学生与第j个学生相互认识. 现在要你将N个学生分成两组,每组中的任意两个学生都不相互认识.
如果N个学生能分组的话,那么就将这N个学生放到尽量多的双人房中去.每个房间放2个相互认识的人.问你最多需要多少房间?
分析:
首先第一步将N个学生分成两类就是看能否将图二分.假设每个学生是一个节点,如果i学生与j学生认识,那么i点和j点之间连一条无向边. 然后我们将图分成两部分,左边部分和右边部分.且各部分内部不存在边,所有边一定是左边与右边点之间的边.(这就是二分图的定义)
判断二分图的话直接用刘汝佳的模板即可.
如果该图能二分, 直观的做法是将所有点重新编号分成左右两边.然后再计算最大匹配. 但是给点重新编号明显比较麻烦,这里我们将原图翻倍处理,然后直接计算出翻倍后图的最大匹配数X. 最终X/2就是我们所求.
翻倍原图具体原理证明在POJ1466:
/article/1517373.html
AC代码:
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 200+10; struct Max_Match { int n; int color[maxn];//颜色数组,用于二分图判定 vector<int> g[maxn]; bool vis[maxn]; int left[maxn]; void init(int n) { this->n=n; for(int i=1;i<=n;i++) g[i].clear(); memset(left,-1,sizeof(left)); } bool bipartite(int u) { for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(color[v] == color[u]) return false; else if(color[v]==0) { color[v]= 3-color[u]; if(!bipartite(v)) return false; } } return true; } bool match(int u) { for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(!vis[v]) { vis[v]=true; if(left[v]==-1 || match(left[v])) { left[v]=u; return true; } } } return false; } int solve() { memset(color,0,sizeof(color)); for(int i=1;i<=n;i++)if(!color[i])//因为该图不一定连通,所以需要所有点做起点判断一遍 { color[i]=1; if(!bipartite(i)) return -1; } int ans=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(match(i)) ans++; } return ans; } }MM; int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { MM.init(n); while(m--) { int u,v; scanf("%d%d",&u,&v); MM.g[u].push_back(v);//判断2分图,由于是无向的,所以需要添加两次边 MM.g[v].push_back(u);//计算原图翻倍的最大匹配,也需要添加两次边 } int ans=MM.solve(); if(ans==-1) printf("No\n"); else printf("%d\n",ans/2); } return 0; }
相关文章推荐
- HDU 2444 The Accomodation of Students (二分图存在的判定以及最大匹配数)
- HDU 2444 The Accomodation of Students(二分图判定+最大匹配)
- HDU 2444 The Accomodation of Students 二分图判定+最大匹配
- HDU 2444 The Accomodation of Students 二分图判定+最大匹配
- HDU 2444 The Accomodation of Students——二分图判定+最大匹配
- HDU 2444 The Accomodation of Students(二分图判定+最大匹配)
- HDU 2444 The Accomodation of Students (二分图判定+最大匹配
- HDU 2444 The Accomodation of Students【二分图判断+最大匹配】
- HDU 2444 The Accomodation of Students (二分图最大匹配+二分图染色)
- HDU 2444 The Accomodation of Students (二分图最大匹配+二分图染色)
- hdu 2444 The Accomodation of Students 二分图判断 + 最大匹配
- hdu 2444 The Accomodation of Students (判断二分图+最大匹配)
- 【二分图判断 && 二分图最大匹配】HDU - 2444 The Accomodation of Students
- HDU 2444 The Accomodation of Students(判断二分图+最大匹配)
- HDU - 2444 The Accomodation of Students(二分图判断+最大匹配)
- hdu 2444 The Accomodation of Students(二分图判断,二分图最大匹配)
- hdu 2444 The Accomodation of Students(判断二分图,二分图最大匹配)
- hdu 2444 The Accomodation of Students (判断二分图,二分图最大匹配)
- hdu 2444 The Accomodation of Students(最大匹配 + 二分图判断)
- hdu 2444 The Accomodation of Students(二分图判断+求最大匹配)