二分图匹配
来源:互联网 发布:联合国维和行动 知乎 编辑:程序博客网 时间:2024/05/21 03:55
(1)一个二分图中的最大匹配数等于这个图中的最小点覆盖数
(2)最小路径覆盖=|G|-最大匹配数
(3)二分图最大独立集=顶点数-二分图最大匹配
邻接矩阵:
///二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式)///初始化:g[][]两边的顶点划分情况///建立g[i][j]表示i->j的有向边,是左边向右边的匹配///g没有边相连则初始化为0///uN是匹配左边的顶点数,vN是匹配右边的顶点数///调用:res=hungary();输出最大匹配数///优点:适用于稠密图,dfs找增广路,实现简洁易于理解///时间复杂度:O(VE)#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<vector>#include<map>#include<set>#include<queue>#include<algorithm>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=505;//顶点编号从0开始int uN,vN;//u,v的数目,使用前必须赋值int g[MAXN][MAXN];//邻接矩阵int linker[MAXN];bool used[MAXN];bool dfs(int u){ for(int v=0;v<vN;v++) { if(g[u][v]&&!used[v]) { used[v]=true; //没有匹配过或者能找到增广路 if(linker[v]==-1||dfs(linker[v])) { linker[v]=u; return true; } } } return false;}int hungary(){ int res=0; memset(linker,-1,sizeof(linker)); for(int u=0;u<uN;u++) { memset(used,false,sizeof(used)); if(dfs(u)) res++; } return res;}int main(){ int T; scanf("%d",&T ); while(T--) { memset(g,0,sizeof(g)); int p,n; scanf("%d%d",&p,&n); uN=p;vN=n; int c,stu; for(int i=0;i<p;i++) { scanf("%d",&c); for(int j=0;j<c;j++) { scanf("%d",&stu ); stu--; g[i][stu]=1; } } int res=hungary(); if(res==p) printf("YES\n"); else printf("NO\n"); } return 0;}/*23 33 1 2 32 1 21 13 32 1 32 1 31 1*/
邻接表:
///匈牙利算法的邻接表形式///使用前用init()进行初始化,给uN赋值///加边使用函数addedge(u,v)#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<vector>#include<map>#include<set>#include<queue>#include<algorithm>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=5e3+5;//点数的最大值const int MAXM=5e4+5;//边数的最大值struct Edge{ int to,nxt;}edge[MAXM];int head[MAXN],tot;void init(){ tot=0; memset(head,-1,sizeof(head));}void addedge(int u,int v){ edge[tot].to=v; edge[tot].nxt=head[u]; head[u]=tot++;}int linker[MAXN];bool used[MAXN];int uN;bool dfs(int u){ for(int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].to; if(!used[v]) { used[v]=true; if(linker[v]==-1||dfs(linker[v])) { linker[v]=u; return true; } } } return false;}int hungary(){ int res=0; memset(linker,-1,sizeof(linker)); for(int u=0;u<uN;u++)//点的编号0~uN-1 { memset(used,false,sizeof(used)); if(dfs(u)) res++; } return res;}int main(){ int T; scanf("%d",&T ); while(T--) { init(); int p,n; scanf("%d%d",&p,&n); uN=p; int c,stu; for(int i=0;i<p;i++) { scanf("%d",&c); for(int j=0;j<c;j++) { scanf("%d",&stu ); stu--; addedge(i,stu); } } int res=hungary(); if(res==p) printf("YES\n"); else printf("NO\n"); } return 0;}/*23 33 1 2 32 1 21 13 32 1 32 1 31 1*/
阅读全文
0 0
- 二分图图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配
- 正则二分图匹配
- 二分图匹配
- 二分图匹配总结
- 二分图最大匹配
- 二分图最大匹配 。
- hdu2119二分图匹配
- 二分图匹配
- 二分图匹配
- 二分图匹配算法
- poj3020-二分图匹配
- 二分图匹配
- 二分图最大匹配
- 二分图最大匹配
- Tr A
- 数组中出现的次数超过数组长度的一半的数字
- 吃豆豆--Java小游戏
- 文件操作——File
- 剑指offer面试题11 数值的整数次方 java实现
- 二分图匹配
- Python小记--文件读写简洁方案
- fzu2282 wand 排列组合 错排
- Android开发中嵌套fragment的实现
- HDU 5869 Different GCD Subarray Query
- tensorflow的运行流程与核心关键概念含义介绍
- 666:放苹果 dfs
- Android 自定义View 之转动风车
- 重启手机后之前新建的VPN消失,且重新添加VPN时提示输入凭据存储的密码