二分图
Posted guoshaoyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图相关的知识,希望对你有一定的参考价值。
二分图简介
二分图是一种图论模型,其特点在于可以将图内的点分进两个集合,而每个集合内部的点没有直接关联,常用的二分图模型有二分图匹配
二分图最大匹配
1. 几种实现方法
1. 匈牙利算法
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int INF=1e9+7,MAXN=1e3+1,MAXM=1e6+1; 5 int N,M,E,ans; 6 int used[MAXN],match[MAXN]; 7 int head[MAXN],to[MAXM],nxt[MAXM],tp; 8 inline void add(int x,int y){ 9 nxt[++tp]=head[x]; 10 head[x]=tp; 11 to[tp]=y; 12 } 13 int dfs(int x){//x->cur vertex 14 for(int i=head[x];i;i=nxt[i]){ 15 if(!used[to[i]]){ 16 used[to[i]]=1; 17 if(!match[to[i]]||dfs(match[to[i]])){ 18 match[to[i]]=x; 19 return 1; 20 } 21 } 22 } 23 return 0; 24 } 25 int main(){ 26 scanf("%d%d%d",&N,&M,&E); 27 for(int i=1;i<=E;i++){ 28 int ii,jj; 29 scanf("%d%d",&ii,&jj); 30 if(ii<=N&&jj<=M){ 31 add(ii,jj); 32 } 33 } 34 for(int i=1;i<=N;i++){ 35 memset(used,0,sizeof(used)); 36 if(dfs(i)){ 37 ans++; 38 } 39 } 40 printf("%d",ans); 41 return 0; 42 }
2.最大流算法(此处是ISAP)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int INF=1e9+7,MAXN=3e3+1,MAXM=2e6+1; 5 int N,M,E; 6 int head[MAXN],to[MAXM*2],nxt[MAXM*2],val[MAXM*2],tp=1; 7 inline void add(int x,int y,int z){ 8 nxt[++tp]=head[x]; 9 head[x]=tp; 10 to[tp]=y; 11 val[tp]=z; 12 nxt[++tp]=head[y]; 13 head[y]=tp; 14 to[tp]=x; 15 } 16 int S,T,de[MAXN],gap[MAXN]; 17 inline void bfs(){ 18 queue<int> que; 19 que.push(T); 20 memset(de,-1,sizeof(de)); 21 de[T]=0; 22 gap[0]=1; 23 while(que.size()){ 24 int idx=que.front(); 25 que.pop(); 26 for(int i=head[idx];i;i=nxt[i]){ 27 if(-1==de[to[i]]){ 28 de[to[i]]=de[idx]+1; 29 gap[de[to[i]]]++; 30 que.push(to[i]); 31 } 32 } 33 } 34 } 35 int maxflow,cur[MAXN]; 36 int dfs(int x,int flow){ 37 if(x==T){ 38 maxflow+=flow; 39 return flow; 40 } 41 int used=0; 42 for(int &i=cur[x];i;i=nxt[i]){ 43 if(val[i]&&de[to[i]]+1==de[x]){ 44 int ii=dfs(to[i],min(flow-used,val[i])); 45 if(ii){ 46 val[i]-=ii; 47 val[i^1]+=ii; 48 used+=ii; 49 if(used==flow){ 50 return used; 51 } 52 } 53 } 54 } 55 gap[de[x]]--; 56 if(!gap[de[x]]){ 57 de[S]=N+M+2; 58 } 59 de[x]++; 60 gap[de[x]]++; 61 return used; 62 } 63 inline void ISAP(){ 64 bfs(); 65 while(de[S]<=N+M+1){ 66 memcpy(cur,head,sizeof(cur)); 67 dfs(S,INF); 68 } 69 printf("%d",maxflow); 70 } 71 int main(){ 72 scanf("%d%d%d",&N,&M,&E); 73 S=0; 74 T=N+M+1; 75 for(int i=1;i<=N;i++){ 76 add(S,i,1); 77 } 78 for(int i=1;i<=M;i++){ 79 add(i+N,T,1); 80 } 81 for(int i=1;i<=E;i++){ 82 int ii,jj; 83 scanf("%d%d",&ii,&jj); 84 if(ii<=N&&jj<=M){ 85 add(ii,jj+N,1); 86 } 87 } 88 ISAP(); 89 return 0; 90 }
2. 简单应用
1. 朴素的匹配问题
这一类问题的就是将一个实际问题转化为用一些对象匹配另一些对象的问题,难点在于建模,思维难度较高。这类问题大多数可以用匈牙利算法,代码短;也可以用网络流,代码长,效率高
例题:
2. 需要输出方案的匹配问题
以上是关于二分图的主要内容,如果未能解决你的问题,请参考以下文章