标签:输出 朴素 turn use 16px emc print bit const
二分图简介
二分图是一种图论模型,其特点在于可以将图内的点分进两个集合,而每个集合内部的点没有直接关联,常用的二分图模型有二分图匹配
二分图最大匹配
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. 需要输出方案的匹配问题
标签:输出 朴素 turn use 16px emc print bit const
原文地址:https://www.cnblogs.com/guoshaoyang/p/10566709.html