LuoguP2756 飞行员配对方案问题(最大流)

Posted blog-dr-j

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",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
",i,to);
116                 }
117             }
118         }
119     }else
120         puts("No Solution!");
121     return 0;
122 }

 

以上是关于LuoguP2756 飞行员配对方案问题(最大流)的主要内容,如果未能解决你的问题,请参考以下文章

有关网络流题目

Luogu P2756 飞行员配对方案问题

luogu P2756 飞行员配对方案问题 网络流24

网络流24题Luogu P2756飞行员配对方案问题

网络流24题 洛谷 2756 飞行员配对方案

P2756 飞行员配对方案问题[二分图最大匹配]