您的位置:首页 > 理论基础 > 计算机网络

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

2017-10-30 16:02 375 查看

题目描述

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

[b]超级源点S与1~m连流量为1的边,m+1~n与超级汇点T连流量为1的边,所给的边,连流量为2e9[/b]

[b]直接dinic,判断边是否有流量,即判断反向边的权值是否不为0[/b]

[b]听说NOIP2017会有网络流????[/b]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct Node
{
int next,to,c;
}edge[20001];
int head[501],num=1,dist[1001],cur[1001],n,m,ans;
void add(int u,int v,int c)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
edge[num].c=c;
}
bool bfs(int S,int T)
{int i;
memset(dist,-1,sizeof(dist));
queue<int>Q;
Q.push(S);
dist[S]=1;
while (!Q.empty())
{
int u=Q.front();
Q.pop();
for (i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if (edge[i].c>0&&dist[v]==-1)
{
dist[v]=dist[u]+1;
Q.push(v);
}
}
}
if (dist[T]==-1) return 0;
return 1;
}
int dfs(int x,int flow,int des)
{
int res=0;
if (x==des) return flow;
for (int &i=cur[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (dist[v]==dist[x]+1&&edge[i].c)
{
int tmp=dfs(v,min(flow-res,edge[i].c),des);
if (tmp<0) continue;
edge[i].c-=tmp;
edge[i^1].c+=tmp;
res+=tmp;
if (res==flow) return res;
}
}
return res;
}
void Dinic(int S,int T)
{
ans=0;
while (bfs(S,T))
{
memcpy(cur,head,sizeof(cur));
int a=0;
while (a=dfs(S,2e9,T)) ans+=a;
}
return;
}
int main()
{int x,y,i,S,T;
cin>>m>>n;
scanf("%d%d",&x,&y);
while (x!=-1&&y!=-1)
{
add(x,y,2e9);
add(y,x,0);
scanf("%d%d",&x,&y);
}
for (i=1;i<=m;i++)
add(0,i,1),add(i,0,0);
for (i=m+1;i<=n;i++)
add(i,n+1,1),add(n+1,i,2e9);
S=0;T=n+1;
Dinic(0,n+1);
if (ans==0)
{
cout<<"No Solution!";
return 0;
}
cout<<ans<<endl;
for (i=2;i<=num;i+=2)
{
if (edge[i].to==S||edge[i^1].to==S) continue;
if (edge[i].to==T||edge[i^1].to==T) continue;
if (edge[i^1].c)
{
printf("%d %d\n",edge[i^1].to,edge[i].to);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: