1. 程式人生 > >P2756 飛行員配對方案問題

P2756 飛行員配對方案問題

bfs 很好 一次 i++ 方案 pop () deep 二次

題目背景

第二次世界大戰時期..

題目描述

英國皇家空軍從淪陷國征募了大量外籍飛行員。由皇家空軍派出的每一架飛機都需要配備在航行技能和語言上能互相配合的2 名飛行員,其中1 名是英國飛行員,另1名是外籍飛行員。在眾多的飛行員中,每一名外籍飛行員都可以與其他若幹名英國飛行員很好地配合。如何選擇配對飛行的飛行員才能使一次派出最多的飛機。對於給定的外籍飛行員與英國飛行員的配合情況,試設計一個算法找出最佳飛行員配對方案,使皇家空軍一次能派出最多的飛機。

對於給定的外籍飛行員與英國飛行員的配合情況,編程找出一個最佳飛行員配對方案,使皇家空軍一次能派出最多的飛機。

輸入輸出格式

輸入格式:

第 1 行有 2 個正整數 m 和 n。n 是皇家空軍的飛行員總數(n<100);m 是外籍飛行員數(m<=n)。外籍飛行員編號為 1~m;英國飛行員編號為 m+1~n。

接下來每行有 2 個正整數 i 和 j,表示外籍飛行員 i 可以和英國飛行員 j 配合。最後以 2個-1 結束。

輸出格式:

第 1 行是最佳飛行員配對方案一次能派出的最多的飛機數 M。接下來 M 行是最佳飛行員配對方案。每行有 2個正整數 i 和 j,表示在最佳飛行員配對方案中,飛行員 i 和飛行員 j 配對。如果所求的最佳飛行員配對方案不存在,則輸出‘No Solution!’。

輸入輸出樣例

輸入樣例#1:
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1
輸出樣例#1:
4
1 7
2 9
3 8
5 10 

設置一個超級源點s,一個超級匯點t,

從s到1-m連一條流量為1的變。從m+1+n到t連一條流量為1的邊。

然後對於s和t中的集合,連一條INF的邊

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5
#include<queue> 6 using namespace std; 7 const int MAXN=200001; 8 const int INF = 1e8; 9 inline void read(int &n) 10 { 11 char c=+;int x=0;bool flag=0; 12 while(c<0||c>9){c=getchar();if(c==-)flag=1;} 13 while(c>=0&&c<=9){x=x*10+c-48;c=getchar();} 14 n=flag==1?-x:x; 15 } 16 int n,m,s,t; 17 struct node 18 { 19 int u,v,flow,nxt; 20 }edge[MAXN]; 21 int head[MAXN]; 22 int cur[MAXN]; 23 int num=0; 24 int deep[MAXN]; 25 int tot=0; 26 void add_edge(int x,int y,int z) 27 { 28 edge[num].u=x;edge[num].v=y; 29 edge[num].flow=z;edge[num].nxt=head[x]; 30 head[x]=num++; 31 } 32 void add(int x,int y,int z) 33 { 34 add_edge(x,y,z); add_edge(y,x,0); 35 } 36 bool BFS() 37 { 38 memset(deep,0,sizeof(deep)); 39 deep[s]=1; queue<int>q; q.push(s); 40 while(q.size()!=0) 41 { 42 int p=q.front(); q.pop(); 43 for(int i=head[p];i!=-1;i=edge[i].nxt) 44 if(!deep[edge[i].v]&&edge[i].flow) 45 deep[edge[i].v]=deep[edge[i].u]+1, q.push(edge[i].v); 46 } 47 return deep[t]; 48 49 } 50 int DFS(int now,int nowflow) 51 { 52 if(now==t||nowflow<=0) return nowflow; 53 int totflow=0; 54 for(int &i=cur[now];i!=-1;i=edge[i].nxt) 55 { 56 if(deep[edge[i].v]==deep[edge[i].u]+1&&edge[i].flow) 57 {int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow)); 58 edge[i].flow-=canflow;edge[i^1].flow+=canflow; 59 totflow+=canflow;nowflow-=canflow; 60 if(nowflow<=0) break;} 61 } 62 return totflow; 63 } 64 void Dinic() 65 { 66 int ans=0; 67 while(BFS()){memcpy(cur,head,MAXN);ans+=DFS(s,1e8);} 68 printf("%d\n",ans); 69 } 70 int vis[101]; 71 int main() 72 { 73 memset(head,-1,sizeof(head)); 74 int n,m; 75 read(m);read(n); 76 s=0;t=n+1; 77 for(int i=1;i<=m;i++) 78 add(s,i,1); 79 for(int i=m+1;i<=n;i++) 80 add(i,t,1); 81 int x,y; 82 while(scanf("%d%d",&x,&y)) 83 { 84 if(x==-1&&y==-1)break; 85 add(x,y,INF); 86 } 87 Dinic(); 88 for(int i=0;i<=num-1;i=i+2) 89 if(edge[i].v!=s&&edge[i].v!=t&&edge[i^1].v!=s&&edge[i^1].v!=t&&edge[i^1].flow) 90 printf("%d %d\n",edge[i].v,edge[i^1].v); 91 return 0; 92 }

P2756 飛行員配對方案問題