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 }