• AC日记——飞行员配对方案问题 洛谷 P2756


    题目背景

    第二次世界大战时期..

    题目描述

    英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    输入输出格式

    输入格式:

    第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 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 

    思路:

      网络流24题之一;

      s到1~m连边,流量为1;

      t到m+1~m+n连边,流量为1;

      跑最大流;

      输出答案;

      然后根据边的流量输出配对方案;

    来,上代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define maxn 205
    #define INF 0x7ffffff
    
    using namespace std;
    
    struct PrintType {
        int first,second;
    };
    struct PrintType ans[maxn];
    
    struct EdgeType {
        int to,next,flow;
    };
    struct EdgeType edge[maxn*100];
    
    int if_z,head[maxn],s,t=maxn-1,deep[maxn],cnt=1,m,n;
    
    char Cget;
    
    inline void in(int &now)
    {
        now=0,if_z=1,Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
    }
    
    inline void edge_add(int u,int v)
    {
        edge[++cnt].to=v,edge[cnt].flow=1,edge[cnt].next=head[u],head[u]=cnt;
        edge[++cnt].to=u,edge[cnt].flow=0,edge[cnt].next=head[v],head[v]=cnt;
    }
    
    bool BFS()
    {
        memset(deep,-1,sizeof(deep));
        queue<int>que;
        que.push(s),deep[s]=0;
        while(!que.empty())
        {
            int pos=que.front();
            for(int i=head[pos];i;i=edge[i].next)
            {
                if(deep[edge[i].to]<0&&edge[i].flow>0)
                {
                    deep[edge[i].to]=deep[pos]+1;
                    if(edge[i].to==t) return true;
                    que.push(edge[i].to);
                }
            }
            que.pop();
        }
        return false;
    }
    
    int flowing(int now,int flow)
    {
        if(now==t||flow<=0) return flow;
        int oldflow=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            if(edge[i].flow<=0||deep[edge[i].to]!=deep[now]+1) continue;
            int pos=flowing(edge[i].to,min(flow,edge[i].flow));
            flow-=pos;
            oldflow+=pos;
            edge[i].flow-=pos;
            edge[i^1].flow+=pos;
            if(flow==0) return oldflow;
        }
        return oldflow;
    }
    
    bool cmp(struct PrintType a,struct PrintType b)
    {
        return a.first<b.first;
    }
    
    void dinic()
    {
        int pos=0;
        while(BFS()) pos+=flowing(s,INF);
        if(pos==0)
        {
            printf("No Solution!
    ");
            return ;
        }
        printf("%d
    ",pos);
        BFS();
        cnt=0;
        for(int i=head[s];i;i=edge[i].next)
        {
            if(edge[i].flow==0)
            {
                for(int j=head[edge[i].to];j;j=edge[j].next)
                {
                    if(edge[j].flow==0)
                    {
                        ans[++cnt].first=edge[i].to;
                        ans[cnt].second=edge[j].to;
                    }
                }
            }
        }
        sort(ans+1,ans+cnt+1,cmp);
        for(int i=1;i<=cnt;i++)
        {
            printf("%d %d
    ",ans[i].first,ans[i].second);
        }
    }
    
    int main()
    {
        in(m),in(n);
        int u,v;
        in(u),in(v);
        while(u!=-1&&v!=-1)
        {
            edge_add(u,v);
            in(u),in(v);
        }
        for(int i=1;i<=m;i++) edge_add(s,i);
        for(int i=1;i<=n;i++) edge_add(i+m,t);
        dinic();
        return 0;
    }
  • 相关阅读:
    康托展开
    Linux Command Line Basics
    hihoCoder 1401 Registration
    C++ 参考网站
    Linux 下的常用工具
    SQL 命令
    GNU MAKE 笔记
    一道基本的计算几何题
    uva 1451 平均值
    bzoj 1826 缓存交换
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6435697.html
Copyright © 2020-2023  润新知