P2756 网络流解决二分图最大匹配

 

P2756 飞行员配对方案问题

题目背景

第二次世界大战时期..

题目描述

P2756 飞行员配对方案问题

英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的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: 复制
3
4 2 1
2 3 2
1
2 3 2 1 2
输出样例#1: 复制
11

说明

样例解释

A耕地种1,2,B耕地种3,收益4+2+3+2=11。

数据范围与约定

1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。

 

 

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<queue>
  6 #include<cstdio>
  7 #define maxn 10005
  8 #define maxm 100005
  9 #define inf 200000000
 10 using namespace std;
 11 struct edge{
 12     int from;
 13     int to;
 14     int flow;
 15     int cap;
 16 };
 17 int cur[maxn],d[maxn];
 18 bool vis [maxn];
 19 int m=0,n,a,b,c,k,s,t;
 20 vector <int> g[maxn];
 21 vector <edge> edges;
 22 void add_edge(int a,int b,int c)
 23 {
 24     m+=2;
 25     edges.push_back({a,b,0,c});
 26     edges.push_back({b,a,0,0});
 27     g[b].push_back(m-1);
 28     g[a].push_back(m-2);
 29 }
 30 bool BFS()
 31 {
 32     
 33     //cout<<"bfs"<<"   1   "<<endl;
 34     memset(vis,0,sizeof(vis));
 35     queue <int> q;
 36     q.push(s);
 37     d[s]=0;
 38     vis[s]=1;
 39     while(! q.empty())
 40     {
 41         
 42         int u=q.front();q.pop();
 43         for(int i=0;i<g[u].size();i++)
 44         {
 45             if(!vis[edges[g[u][i]].to]&&edges[g[u][i]].cap>edges[g[u][i]].flow)
 46             {    
 47                 d[edges[g[u][i]].to]=d[u]+1;
 48                 vis[edges[g[u][i]].to]=1;
 49                 
 50                 q.push(edges[g[u][i]].to);
 51             }
 52         }
 53     }
 54     return vis[t];
 55 }
 56 long long dfs(int x,int a)
 57 {
 58     if (x==t || a==0) return a;
 59     long long flow=0;int f;
 60     for(int &i=cur[x]; i< g[x].size(); i++)
 61     {
 62         if (d[x]+1==d[edges[g[x][i]].to] && (f=dfs(edges[g[x][i]].to,min(a,edges[g[x][i]].cap-edges[g[x][i]].flow)))>0)
 63         {
 64             edges[g[x][i]].flow+=f;
 65             edges[g[x][i]^1].flow-=f;
 66             flow+=(long long)1*f;
 67             a-=f;
 68             if (a==0) break;
 69         }
 70     }
 71     return flow;
 72     
 73 }
 74 int maxflow(int s,int t)
 75 {
 76     long long flow=0;
 77     while(BFS()==1)
 78     {
 79         memset(cur,0,sizeof(cur));
 80         flow+=(long long)dfs(s,inf);
 81     }
 82     return flow;
 83 }
 84 int main()
 85 {
 86     cin>>n>>k;
 87     s=0;t=k+1;c=0;
 88     for(int i=1;i<=n;i++)
 89     {
 90         add_edge(s,i,1);
 91     }
 92     for(int i=n+1;i<=k;i++)
 93     {
 94         add_edge(i,t,1);
 95     }
 96     cin>>a>>b;
 97     while(a!=-1)
 98     {    
 99         c++;
100         add_edge(a,b,1);
101         cin>>a>>b;
102     }
103     int flow=maxflow(s,t);
104     if(!flow) printf("No answer\n");
105     else{
106         printf("%d\n",flow);
107         for(int i=1;i<=n;i++)
108             for(int j=0;j<g[i].size();j++) 
109                 if(edges[g[i][j]].cap==1 &&edges[g[i][j]].flow==1) printf("%d %d\n",i,edges[g[i][j]].to);
110                 //如果这条边是满的并且不为反向边,说明这两个点是匹配的
111     }
112 
113     return 0;
114 }

 

posted @ 2018-04-10 14:57  zZ1358m  阅读(354)  评论(1编辑  收藏  举报