简单的二分图匹配问题。
GO:洛谷
水水就过了。
配对方案从边里面找:
- 一定是权值为0的边
- 源点一定在1~m间,汇点一定在m+1~n间
- 直接输出即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1100; 4 const int inf=1e9; 5 int m,n,S,T,cnt=-1,maxflow; 6 int d[N],head[N<<1]; 7 struct edge{int to,next,f,from;}e[N<<1]; 8 void addedge(int from,int to,int f){e[++cnt]=(edge){to,head[from],f,from};head[from]=cnt;} 9 inline bool bfs(){ 10 memset(d,0,sizeof(d)); 11 queue<int>q; 12 q.push(S); 13 d[S]=1; 14 while(q.size()){ 15 int u=q.front(); 16 q.pop(); 17 for(int i=head[u];i!=-1;i=e[i].next){ 18 int v=e[i].to,f=e[i].f; 19 if(d[v]||!f) continue; 20 d[v]=d[u]+1; 21 q.push(v); 22 if(v==T) return 1; 23 } 24 } 25 return 0; 26 } 27 28 int dinic(int u,int flow){ 29 if(u==T) return flow; 30 int rest=flow; 31 for(int i=head[u];i!=-1&&rest;i=e[i].next){ 32 int v=e[i].to,f=e[i].f; 33 if(!f||d[v]!=d[u]+1) continue; 34 int k=dinic(v,min(rest,f)); 35 if(!k) d[v]=0; 36 else{ 37 e[i].f-=k; 38 e[i^1].f+=k; 39 rest-=k; 40 } 41 } 42 return flow-rest; 43 } 44 void solve(){ 45 int now=0; 46 while(bfs()){ 47 while(now=dinic(S,inf)) 48 maxflow+=now; 49 } 50 if(!maxflow){ 51 printf("No Solution!"); 52 } 53 else{ 54 printf("%d\n",maxflow); 55 for(int i=0;i<=cnt;i++){ 56 if(!e[i].f&&e[i].from>0&&e[i].from<=m&&e[i].to>m&&e[i].to<=n){ 57 printf("%d %d\n",e[i].from,e[i].to); 58 } 59 } 60 } 61 } 62 int main(){ 63 memset(head,-1,sizeof(head)); 64 scanf("%d%d",&m,&n); 65 int x=0,y=0; 66 S=0,T=n+1; 67 while(1){ 68 scanf("%d%d",&x,&y); 69 if(x<0) break; 70 addedge(x,y,1); 71 addedge(y,x,0); 72 } 73 for(int i=1;i<=m;i++){ 74 addedge(S,i,1); 75 addedge(i,S,0); 76 } 77 for(int i=m+1;i<=n;i++){ 78 addedge(i,T,1); 79 addedge(T,i,0); 80 } 81 solve(); 82 return 0; 83 }
切题真爽!