1. 程式人生 > >飛行員配對方案問題(網絡流24題)

飛行員配對方案問題(網絡流24題)

urn getchar() put solution -a 註意 std 輸出格式 name

洛谷題目鏈接:飛行員配對方案問題

題目背景

第二次世界大戰時期..

題目描述

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

一道網絡流的入門題,這篇博客主要是介紹一下模板,並講一下這道題的做法。
題意大概就是給出一個二分圖(左右兩邊互不相通),然後要求出最大的配對數,可以用匈牙利算法,這裏用網絡流來做。
那麽我們分析一下這個問題,假設我們把本國飛行員放在一邊,把外國飛行員放在一邊,那麽組成一組配對的前提就是從左邊有一條邊到右邊,一個飛行員只能與一個飛行員配對,那麽我們在建邊的時候就可以把流量設為1,然後把每個配對關系都建一條殘量為1的邊,跑出來的最大流就是答案。
另外記得仔細讀題!!!註意m,n所表示的含義。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 using namespace std;
  6 const int inf=2147483647;
  7 const int N=100;
  8 
  9 int s,t,ans=0;
 10 int n,m,cnt=1;
 11 int lev[N+10];
 12 int last[N+10];
 13 int lis[100100];
 14 
 15 struct edge{
 16   int to,next,cap;
 17 }e[2*N*N+10];
 18 
 19 int minn(int a,int b){
 20   if(a>b) return b;
 21   return a;
 22 }
 23 
 24 int gi(){
 25   int ans=0,f=1;char i=getchar();
 26   while(i<0||i>9){if(i==-)f=-1;i=getchar();}
 27   while(i<=9&&i>=0){ans=(ans<<1)+(ans<<3)+i-0;i=getchar();}
 28   return ans*f;
 29 }
 30 
 31 int buf[30];
 32 
 33 void write(int x)
 34 {
 35     if (x<0) putchar(-),x=-x;
 36     buf[0]=0;
 37     while (x) buf[++buf[0]]=x%10,x/=10;
 38     if (!buf[0]) buf[0]=1,buf[1]=0;
 39     while (buf[0]) putchar(0+buf[buf[0]--]);
 40 }
 41 
 42 void add(int x,int y,int z){
 43   e[++cnt].to=y;
 44   e[cnt].cap=z;
 45   e[cnt].next=last[x];
 46   last[x]=cnt;
 47 }
 48 
 49 bool bfs(){
 50   int head=0,tail=0;
 51   lis[tail++]=s;
 52   memset(lev,-1,sizeof(lev));
 53   lev[s]=0;
 54   while(head<tail){
 55     int x=lis[head++];
 56     for(int i=last[x];i;i=e[i].next){
 57       int to=e[i].to;
 58       if(lev[to]==-1&&e[i].cap){
 59     lev[to]=lev[x]+1;
 60     lis[tail++]=to;
 61       }
 62     }
 63   }
 64   if(lev[t]!=-1) return true;
 65   return false;
 66 }
 67 
 68 int dfs(int x,int flow){
 69   int rest=0;
 70   if(x==t) return flow;
 71   for(int i=last[x];i;i=e[i].next){
 72     int to=e[i].to;
 73     if(lev[to]==lev[x]+1&&e[i].cap){
 74       int f=dfs(to,minn(flow-rest,e[i].cap));
 75     //  if(f){
 76     rest+=f;
 77     e[i].cap-=f;
 78     e[i^1].cap+=f;
 79     //  }
 80       if(rest==flow) return flow;
 81     }
 82   }
 83   if(!rest)lev[x]=-1;
 84   return rest;
 85 }
 86 
 87 int main(){
 88   int x,y;
 89   n=gi();m=gi();
 90   s=0,t=m+1;
 91   for(int i=1;i<=n;i++)
 92     add(0,i,1),add(i,0,0);
 93   for(int i=n+1;i<=m;i++)
 94     add(i,m+1,1),add(m+1,i,0);
 95   while(1){
 96     x=gi();y=gi();
 97     if(x==-1&&y==-1) break;
 98     add(x,y,1);add(y,x,0);
 99   }
100   while(bfs()) ans+=dfs(s,inf);
101   if(ans){
102     printf("%d\n",ans);
103     for(int i=1;i<=n;i++)
104       for(int j=last[i];j;j=e[j].next)
105     if(!e[j].cap&&e[j].to!=0) write(i),putchar( ),write(e[j].to),putchar(\n);
106   }
107   else printf("No Solution!\n");
108   return 0;
109 }

本來一個簡單的模板因為審題不清搞成這個鬼樣。。

 

飛行員配對方案問題(網絡流24題)