洛谷——P2756 飛行員配對方案問題

P2756 飛行員配對方案問題

題目背景

第二次世界大戰時期..html

題目描述

英國皇家空軍從淪陷國徵募了大量外籍飛行員。由皇家空軍派出的每一架飛機都須要配備在航行技能和語言上能互相配合的2 名飛行員,其中1 名是英國飛行員,另1名是外籍飛行員。在衆多的飛行員中,每一名外籍飛行員均可以與其餘若干名英國飛行員很好地配合。如何選擇配對飛行的飛行員才能使一次派出最多的飛機。對於給定的外籍飛行員與英國飛行員的配合狀況,試設計一個算法找出最佳飛行員配對方案,使皇家空軍一次能派出最多的飛機。ios

對於給定的外籍飛行員與英國飛行員的配合狀況,編程找出一個最佳飛行員配對方案,使皇家空軍一次能派出最多的飛機。算法

輸入輸出格式

輸入格式:編程

 

第 1 行有 2 個正整數 m 和 n。n 是皇家空軍的飛行員總數(n<100);m 是外籍飛行員數(m<=n)。外籍飛行員編號爲 1~m;英國飛行員編號爲 m+1~n。網絡

接下來每行有 2 個正整數 i 和 j,表示外籍飛行員 i 能夠和英國飛行員 j 配合。最後以 2個-1 結束。spa

 

輸出格式:設計

 

第 1 行是最佳飛行員配對方案一次能派出的最多的飛機數 M。接下來 M 行是最佳飛行員配對方案。每行有 2個正整數 i 和 j,表示在最佳飛行員配對方案中,飛行員 i 和飛行員 j 配對。若是所求的最佳飛行員配對方案不存在,則輸出‘No Solution!’。rest

 

輸入輸出樣例

輸入樣例#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 

 

網絡流code

建一個原點和一個匯點,而後讓原點與全部的第一類飛行員連邊,第二種飛行員與匯點連流量爲1的邊,每兩個配對的點之間連邊(邊權任意),而後跑網絡流htm

 

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100100
#define maxn 9999999
using namespace std;
queue<int>q;
int n,m,x,y,tot=1,ans,s,e;
int to[N],cap[N],lev[N],cnt[N],head[N],nextt[N];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int add(int x,int y,int z)
{
    ++tot;to[tot]=y,cap[tot]=z,nextt[tot]=head[x];head[x]=tot;
    ++tot;to[tot]=x,cap[tot]=0,nextt[tot]=head[y];head[y]=tot;
}
inline bool bfs()
{
    while(!q.empty()) q.pop();
    for(int i=s;i<=e;i++)
    {
        lev[i]=-1;
        cnt[i]=head[i];
    }
    q.push(s),lev[s]=0;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nextt[i])
        {
            int t=to[i];
            if(cap[i]>0&&lev[t]==-1)
            {
                lev[t]=lev[x]+1;
                q.push(t);
                if(t==e) return true;
            }
        }
    }
    return false;
}
int dinic(int x,int flow)
{
    if(x==e) return flow;
    int rest=0,delta;
    for(int &i=cnt[x];i;i=nextt[i])
    {
        int t=to[i];
        if(cap[i]>0&&lev[t]==lev[x]+1)
        {
            delta=dinic(t,min(cap[i],flow-rest));
            if(delta)
            {
                rest+=delta;
                cap[i]-=delta;
                cap[i^1]+=delta;
                if(rest==flow) break;
            }
        }
    }
    if(rest!=flow) lev[x]=-1;
    return rest;
}
int main()
{
    m=read(),n=read();
    s=0,e=n+1;
    for(int i=1;i<=m;i++)
     add(s,i,1);
    for(int i=m+1;i<=n;i++)
     add(i,e,1);
    while(1)
    {
        x=read(),y=read();
        if(x==-1&&y==-1) break;
        add(x,y,maxn);
    }
    while(bfs())
        ans+=dinic(s,maxn);
    printf("%d\n",ans);
    if(ans==0)
    {
        printf("No Solution!\n");
        return 0;
    }
    for(int i=1;i<=m;i++)
     for(int j=head[i];j;j=nextt[j])
     {
         if(cap[j]==maxn||to[j]==s)
        continue;
        printf("%d %d\n",i,to[j]);
      } 
    return 0;
}

咱們還能夠用匈牙利算法來作這道題
http://www.cnblogs.com/z360/p/7123377.html

相關文章
相關標籤/搜索