[网络流24题]飞行员配对方案问题
题目背景
第二次世界大战时期..
题目描述
英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
第 1 行是最佳飞行员配对方案一次能派出的最多的飞机数 M。接下来 M 行是最佳飞行员配对方案。每行有 2个正整数 i 和 j,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。
题解
就先从这到基础题开始吧
没啥可讲的,就是最大二分图匹配,题面也没绕什么弯子。。。
从原点s向所有外籍飞行员连一条容量为1的边,
老外想看得顺眼的英国人连容量无限的边,
英国人向汇点t连容量为1的边。。。
跑一遍最大流!
完了
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,st,ed,ans; 7 int head[405]; 8 int cur[405]; 9 int dis[405]; 10 int pre[405]; 11 int usd[405]; 12 struct Edge{ 13 int fr; 14 int to; 15 int flw; 16 int nxt; 17 }edge[400005]; 18 void addedge(int u,int v,int f){ 19 edge[cnt].fr=u; 20 edge[cnt].to=v; 21 edge[cnt].flw=f; 22 edge[cnt].nxt=head[u]; 23 head[u]=cnt++; 24 edge[cnt].fr=v; 25 edge[cnt].to=u; 26 edge[cnt].flw=0; 27 edge[cnt].nxt=head[v]; 28 head[v]=cnt++; 29 } 30 void init(){ 31 memset(head,-1,sizeof(head)); 32 } 33 int bfs(){ 34 queue<int>que; 35 memset(dis,0x3f,sizeof(dis)); 36 que.push(st);dis[st]=0; 37 while(!que.empty()){ 38 int u=que.front(); 39 que.pop(); 40 for(int i=head[u];i!=-1;i=edge[i].nxt){ 41 int v=edge[i].to; 42 if(!edge[i].flw)continue; 43 if(dis[v]==0x3f3f3f3f){ 44 dis[v]=dis[u]+1; 45 que.push(v); 46 } 47 } 48 } 49 return dis[ed]!=0x3f3f3f3f; 50 } 51 int dfs(int u,int flw){ 52 if(u==ed)return flw; 53 int All=0,tmp; 54 for(int i=cur[u];i!=-1;i=edge[i].nxt){ 55 if(!edge[i].flw)continue; 56 int v=edge[i].to;cur[u]=i; 57 if(dis[v]!=dis[u]+1)continue; 58 if((tmp=dfs(v,min(flw,edge[i].flw)))>0){ 59 edge[i].flw-=tmp; 60 edge[i^1].flw+=tmp; 61 flw-=tmp,All+=tmp; 62 pre[v]=u; 63 if(!flw)break; 64 } 65 } 66 return All; 67 } 68 int dinic(){ 69 int ret=0; 70 while(bfs()){ 71 memcpy(cur,head,sizeof(cur)); 72 ret+=dfs(st,0x3f3f3f3f); 73 } 74 return ret; 75 } 76 int main(){ 77 init(); 78 scanf("%d%d",&m,&n);ed=n+1; 79 while(true){ 80 int x,y; 81 scanf("%d%d",&x,&y); 82 if((x==-1)&&(y==-1))break; 83 addedge(x,y,1); 84 } 85 for(int i=1;i<=m;i++){ 86 addedge(st,i,1); 87 } 88 for(int i=m+1;i<=n;i++){ 89 addedge(i,ed,1); 90 } 91 ans=dinic(); 92 if(!ans){ 93 printf("No Solution!\n"); 94 } 95 printf("%d\n",ans); 96 for(int i=m+1;i<=n;i++){ 97 int x=pre[i]; 98 int y=i; 99 if(x){ 100 printf("%d %d\n",x,y); 101 } 102 } 103 return 0; 104 }