网络流二十四题之一 飞行员配对问题

来源:互联网 发布:腾达路由器mac怎么改 编辑:程序博客网 时间:2024/05/21 11:01

«问题描述:
第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出
的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞
行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英
国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的
外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空
军一次能派出最多的飞机。
«编程任务:
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,
使皇家空军一次能派出最多的飞机。
«数据输入:
由文件input.txt提供输入数据。文件第1 行有2个正整数m和n。n是皇家空军的飞行
员总数(n<100);m是外籍飞行员数。外籍飞行员编号为1~m;英国飞行员编号为m+1~n。
接下来每行有2个正整数i和j,表示外籍飞行员i可以和英国飞行员j配合。文件最后以2
个-1 结束。
«结果输出:
程序运行结束时,将最佳飞行员配对方案输出到文件output.txt 中。第1 行是最佳飞行
员配对方案一次能派出的最多的飞机数M。接下来M 行是最佳飞行员配对方案。每行有2
个正整数i和j,表示在最佳飞行员配对方案中,飞行员i和飞行员j 配对。
如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。

输入文件示例 输出文件示例
input.txt output.txt
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1

输出:
4
1 7
2 9
3 8
5 10
这道题真的有毒,为什么我总是得不出正确的分配结果,还说这道题有多解……以后在研究吧。
这道题是二分图匹配,用源点接外国飞行员,汇点接英国飞行员,中间按照输入连就行

#include <cstdio>#include <iostream>#include <stack>#include <cstring>using namespace std;const int INF=0x3f3f3f3f;const int MAXN=150;//点数的最大值const int MAXM=20500;//边数的最大值struct Node{    int from,to,next;    int cap;}edge[MAXM];int tol;int dep[MAXN];//dep为点的层次int head[MAXN];int n;void init(){    tol=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int w)//第一条变下标必须为偶数{    edge[tol].from=u;    edge[tol].to=v;    edge[tol].cap=w;    edge[tol].next=head[u];    head[u]=tol++;    edge[tol].from=v;    edge[tol].to=u;    edge[tol].cap=0;    edge[tol].next=head[v];    head[v]=tol++;}int BFS(int start,int end){    int que[MAXN];    int front,rear;    front=rear=0;    memset(dep,-1,sizeof(dep));    que[rear++]=start;    dep[start]=0;    while(front!=rear)    {        int u=que[front++];        if(front==MAXN)front=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].to;            if(edge[i].cap>0&&dep[v]==-1)            {                dep[v]=dep[u]+1;                que[rear++]=v;                if(rear>=MAXN)rear=0;                if(v==end)return 1;            }        }    }    return 0;}int dinic(int start,int end){    int res=0;    int top;    int stack[MAXN];//stack为栈,存储当前增广路    int cur[MAXN];//存储当前点的后继    while(BFS(start,end))    {        memcpy(cur,head,sizeof(head));        int u=start;        top=0;        while(1)        {            if(u==end)            {                int min=INF;                int loc;                for(int i=0;i<top;i++)                  if(min>edge[stack[i]].cap)                  {                      min=edge[stack[i]].cap;                      loc=i;                  }                for(int i=0;i<top;i++)                {                    edge[stack[i]].cap-=min;                    edge[stack[i]^1].cap+=min;                }                res+=min;                top=loc;                u=edge[stack[top]].from;            }            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)              if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])                 break;            if(cur[u]!=-1)            {                stack[top++]=cur[u];                u=edge[cur[u]].to;            }            else            {                if(top==0)break;                dep[u]=-1;                u=edge[stack[--top]].from;            }        }    }    return res;}void print_all_edge(){    for(int i = 0;i<tol;i+=2)    {        printf("%d->%d left = %d\n",edge[i].from,edge[i].to,edge[i].cap);    }}int m;int main(){    scanf("%d%d",&m,&n);    int u,v;    init();    for(int i = 1;i<=m;i++)    {        addedge(0,i,1);    }    for(int i = m+1;i<=n;i++)    {        addedge(i,n+1,1);    }    while(scanf("%d%d",&u,&v)!=EOF)    {        if(u == -1) break;        addedge(u,v,1);    }    int ans = dinic(0,n+1);    print_all_edge();    if(ans)printf("%d\n",ans);    else    {        printf("No Solution!\n");    }    return 0;}
原创粉丝点击