1. 程式人生 > >LuoguP2756 飛行員配對方案問題(最大流)

LuoguP2756 飛行員配對方案問題(最大流)

題目背景

第二次世界大戰時期..

題目描述

英國皇家空軍從淪陷國徵募了大量外籍飛行員。由皇家空軍派出的每一架飛機都需要配備在航行技能和語言上能互相配合的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!’。

解題思路:

這個顯然是二分圖最大匹配,最後要輸出方案還是寫最大流吧。

最大流解決二分圖最大匹配問題,建一個源點,建一個匯點,

源點與前N個點連$∞$,後M個與匯點連$∞$,中間建1的邊。

最大流就是最大匹配。

程式碼:

 

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 const int oo=0x3f3f3f3f;
  6 struct pnt{
  7     int hd;
  8     int lyr;
  9     int now;
10 }p[10001]; 11 struct ent{ 12 int twd; 13 int lst; 14 int vls; 15 }e[100000]; 16 int n,m; 17 int s,t; 18 int cnt; 19 std::queue<int>Q; 20 void ade(int f,int t,int v) 21 { 22 cnt++; 23 e[cnt].twd=t; 24 e[cnt].vls=v; 25 e[cnt].lst=p[f].hd; 26 p[f].hd=cnt; 27 return ; 28 } 29 bool Bfs(void) 30 { 31 while(!Q.empty()) 32 Q.pop(); 33 for(int i=1;i<=n+m+2;i++) 34 p[i].lyr=0; 35 p[s].lyr=1; 36 Q.push(s); 37 while(!Q.empty()) 38 { 39 int x=Q.front(); 40 Q.pop(); 41 for(int i=p[x].hd;i;i=e[i].lst) 42 { 43 int to=e[i].twd; 44 if(p[to].lyr==0&&e[i].vls>0) 45 { 46 p[to].lyr=p[x].lyr+1; 47 if(to==t) 48 return true; 49 Q.push(to); 50 } 51 } 52 } 53 return false; 54 } 55 int Dfs(int x,int fll) 56 { 57 if(x==t) 58 return fll; 59 for(int &i=p[x].now;i;i=e[i].lst) 60 { 61 int to=e[i].twd; 62 if(p[to].lyr==p[x].lyr+1&&e[i].vls>0) 63 { 64 int ans=Dfs(to,std::min(fll,e[i].vls)); 65 if(ans>0) 66 { 67 e[i].vls-=ans; 68 e[((i-1)^1)+1].vls+=ans; 69 return ans; 70 } 71 } 72 } 73 return 0; 74 } 75 int Dinic(void) 76 { 77 int ans=0; 78 while(Bfs()) 79 { 80 for(int i=1;i<=n+m+2;i++) 81 p[i].now=p[i].hd; 82 int dlt; 83 while(dlt=Dfs(s,oo)) 84 ans+=dlt; 85 } 86 return ans; 87 } 88 int main() 89 { 90 //freopen("a.in","r",stdin); 91 scanf("%d%d",&n,&m); 92 s=n+m+1,t=s+1; 93 for(int i=1;i<=n;i++)ade(s,i,1),ade(i,s,0); 94 for(int i=1;i<=m;i++)ade(i+n,t,1),ade(t,i+n,0); 95 while(true) 96 { 97 int a,b; 98 scanf("%d%d",&a,&b); 99 if(a==-1&&b==-1) 100 break; 101 ade(a,b,1); 102 ade(b,a,0); 103 } 104 int ans=Dinic(); 105 if(ans) 106 { 107 printf("%d\n",ans); 108 for(int i=1;i<=n;i++) 109 { 110 for(int j=p[i].hd;j;j=e[j].lst) 111 { 112 int to=e[j].twd; 113 if(e[j].vls==0&&to>n&&to<=n+m) 114 { 115 printf("%d %d\n",i,to); 116 } 117 } 118 } 119 }else 120 puts("No Solution!"); 121 return 0; 122 }