题解:将外籍飞行员与源点建容量为1的边,英国飞行员与汇点建容量为1的边,外籍飞行员和英国飞行员有边就建容量为1的边,跑最大流。
输出方案:原边满流且端点非源点汇点就输出。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=110,M=2e4+100,inf=1e9; 4 int h[N],e[M],ne[M],f[M],idx; 5 int cur[N],d[N]; 6 int n,m,S,T; 7 void add(int a,int b,int c) 8 { 9 ne[idx]=h[a],f[idx]=c,e[idx]=b,h[a]=idx++; 10 ne[idx]=h[b],f[idx]=0,e[idx]=a,h[b]=idx++; 11 } 12 bool bfs() 13 { 14 memset(d,-1,sizeof d); 15 queue<int>q; 16 q.push(S); 17 cur[S]=h[S]; 18 d[S]=0; 19 while(q.size()) 20 { 21 int t=q.front(); 22 q.pop(); 23 for(int i=h[t];i!=-1;i=ne[i]) 24 { 25 int j=e[i]; 26 if(d[j]==-1&&f[i]) 27 { 28 d[j]=d[t]+1; 29 cur[j]=h[j]; 30 if(j==T)return true; 31 q.push(j); 32 } 33 } 34 } 35 return false; 36 } 37 int find(int u,int limit) 38 { 39 if(u==T)return limit; 40 int flow=0; 41 for(int i=cur[u];i!=-1&&flow<limit;i=ne[i]) 42 { 43 int j=e[i]; 44 cur[u]=i; 45 if(d[j]==d[u]+1&&f[i]) 46 { 47 int t=find(j,min(f[i],limit-flow)); 48 if(!t)d[j]=-1; 49 f[i]-=t,f[i^1]+=t,flow+=t; 50 } 51 } 52 return flow; 53 } 54 int dinic() 55 { 56 int r=0,flow; 57 while(bfs())while(flow=find(S,inf))r+=flow; 58 return r; 59 } 60 int main() 61 { 62 memset(h,-1,sizeof h); 63 cin>>m>>n; 64 S=0,T=n+1; 65 int x,y; 66 for(int i=1;i<=m;i++) 67 add(S,i,1); 68 while(cin>>x>>y) 69 { 70 if(x==-1&&y==-1) 71 { 72 break; 73 } 74 add(x,y,1); 75 } 76 for(int i=m+1;i<=n;i++) 77 add(i,T,1); 78 printf("%d ",dinic()); 79 for(int i=0;i<idx;i+=2) 80 { 81 int a=e[i^1],b=e[i]; 82 if(a==S||b==T||f[i])continue; 83 printf("%d %d ",a,b); 84 } 85 }