二分图
2015-04-25 22:47
162 查看
设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
二分图判定:
BFS就可以,一边搜一边给点上色,遇到相邻的点。如果没上色,则给它上不同的颜色,并且加入队列。如果有颜色了,判断跟现在的点颜色是否一样,一样则说明不是二分图。
例题:http://blog.csdn.net/youthinkwu/article/details/43898767
二分图的最大匹配:匈牙利算法
先来说说几个概念:
匹配:G为二分图的边集的子集,且任意两条边都没有相同的顶点,称该子边集为一个匹配。
最大匹配:边数最多的匹配称为最大匹配。
完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。
最小覆盖: 假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。可以证明:最少的点(即覆盖数)=最大匹配数(我并不会证明)。
最大独立集问题:
在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值.
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = 总点数 - 最小覆盖集 = N - 最大匹配数
最小路径覆盖:
用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i’,如果有边i->j,则在二分图中引入边i->j’,设二分图最大匹配为m,则结果就是n-m。
交错轨(路):是图的一条简单路径,满足任意相邻的两条边,一条在匹配内,一条不在匹配内。
增广轨(路):是一个始点与终点都为未匹配点的交错轨。
二分图最大匹配问题的匈牙利算法: 枚举左边点,不断寻找增广(轨)路,有增广(轨)路就说明还能增加一条边,一直寻找到再也找不到增广(轨)路为止,求出的就是最大匹配。
时间复杂度:左边点N,右边点M,边数E;
邻接表 O(NE)
邻接矩阵 O(MN^2)
最大匹配:(邻接矩阵写法)
上面那种是能明确分出左右两边点的,有些题目是很难划分两边点的,直接对一个集合求最大匹配,那么匹配出来的ans是答案的两倍,需要除以2.
二分图判定:
BFS就可以,一边搜一边给点上色,遇到相邻的点。如果没上色,则给它上不同的颜色,并且加入队列。如果有颜色了,判断跟现在的点颜色是否一样,一样则说明不是二分图。
例题:http://blog.csdn.net/youthinkwu/article/details/43898767
二分图的最大匹配:匈牙利算法
先来说说几个概念:
匹配:G为二分图的边集的子集,且任意两条边都没有相同的顶点,称该子边集为一个匹配。
最大匹配:边数最多的匹配称为最大匹配。
完美匹配: 如果所有点都在匹配边上,称这个最大匹配是完美匹配。
最小覆盖: 假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。可以证明:最少的点(即覆盖数)=最大匹配数(我并不会证明)。
最大独立集问题:
在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值.
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = 总点数 - 最小覆盖集 = N - 最大匹配数
最小路径覆盖:
用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i’,如果有边i->j,则在二分图中引入边i->j’,设二分图最大匹配为m,则结果就是n-m。
交错轨(路):是图的一条简单路径,满足任意相邻的两条边,一条在匹配内,一条不在匹配内。
增广轨(路):是一个始点与终点都为未匹配点的交错轨。
二分图最大匹配问题的匈牙利算法: 枚举左边点,不断寻找增广(轨)路,有增广(轨)路就说明还能增加一条边,一直寻找到再也找不到增广(轨)路为止,求出的就是最大匹配。
时间复杂度:左边点N,右边点M,边数E;
邻接表 O(NE)
邻接矩阵 O(MN^2)
最大匹配:(邻接矩阵写法)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> const int maxn = 300; int g[maxn][maxn],match[maxn],n,m//g邻接矩阵,match[i] = j 表示右边的点i跟左边的点j匹配,n是左边点的个数,m是右边点的个数; bool vis[maxn]; using namespace std; bool DFS(int u)//寻找增广(轨)路 { for(int i = 1; i <= m; i++) { if(g[u][i] && !vis[i]) { vis[i] = 1; if(match[i] == -1 || DFS(match[i])) { match[i] = u; return true; } } } return false; } int main() { while(~scanf("%d%d",&n,&m)) { memset(g,0,sizeof(g)); memset(match,-1,sizeof(match)); for(int i = 1; i <= n; i++) { int t; scanf("%d",&t); while(t--) { int u; scanf("%d",&u); g[u][i] = 1;//单向边就可以。 } } int ans = 0; for(int i = 1; i <= n; i++)//求最大匹配。 { memset(vis,0,sizeof(vis)); if(DFS(i)) ans ++; } printf("%d\n",ans); } return 0; }
上面那种是能明确分出左右两边点的,有些题目是很难划分两边点的,直接对一个集合求最大匹配,那么匹配出来的ans是答案的两倍,需要除以2.
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> const int maxn = 300; int g[maxn][maxn],match[maxn],n //g邻接矩阵,match[i] = j 表示点i跟点j匹配,n是点的总个数; bool vis[maxn]; using namespace std; bool DFS(int u)//寻找增广(轨)路 { for(int i = 1; i <= n; i++)//这里是n不是m了。 { if(g[u][i] && !vis[i]) { vis[i] = 1; if(match[i] == -1 || DFS(match[i])) { match[i] = u; return true; } } } return false; } int main() { while(~scanf("%d%d",&n,&m)) { memset(g,0,sizeof(g)); memset(match,-1,sizeof(match)); for(int i = 1; i <= n; i++) { int t; scanf("%d",&t); while(t--) { int u; scanf("%d",&u); g[u][i] = 1; g[i][u]/这里需要双向边。 } } int ans = 0; for(int i = 1; i <= n; i++)//求最大匹配。 { memset(vis,0,sizeof(vis)); if(DFS(i)) ans ++; } printf("%d\n",ans); } return 0; }
相关文章推荐
- 洛谷 1330 封锁阳光大学 图论 二分图染色
- hdu 2444 The Accomodation of Students (二分图判定+匈牙利算法)
- 二分图——二分图最大匹配
- *HDU1150 二分图
- poj 2942 点双连通分量+二分图染色
- poj_3308 Paratroopers(二分图最小点权覆盖集+dinic+化乘为加)
- 二分图最大匹配的可行边和必须边
- HDU 4751 Divide Groups(二分图判断)
- poj 2728 二分图
- poj3692(二分图最大独立集)
- HDU1179-二分图最大匹配
- HDU2768-二分图最大独立集
- Uva 10888 Warehouse(二分图最大权匹配)
- POJ 2125 Destroying The Graph 二分图 最小点权覆盖
- 二分图的最大匹配、完美匹配和匈牙利算法
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
- 二分图最大匹配算法模板
- [hdu2444] 二分图判断与匹配
- 二分图最大匹配
- [Sdoi2017]新生舞会 [01分数规划 二分图最大权匹配]