题解 P2756 【飞行员配对方案问题】

· · 题解

题目名称:飞行员配对方案问题

来源:网络流24题

链接

博客链接

题目链接

题目大意

有n个英国空军和m个外籍空军,一架飞机需要一对互相配合的英国空军和外籍空军配合。给出配合情况,求出最多能发动多少飞机。

提示

注意题目来源!

题解

这是一道最大流裸题。

从原点开始,向每个外籍飞行员连边,容量为1。(因为每个外籍飞行员只能被指派一次)

如果外籍飞行员i与英国飞行员j配合,那么就从i向j连边,容量为1。(每个外籍飞行员与每个英国飞行员最多配合一次)

从每个英国飞行员向汇点连边,容量为1。(一对飞行员相互配合只能发动一架飞机)

拿样例说话,如图所示 其中F表示外籍飞行员,E表示英国飞行员。

然后跑一遍Dinic就得到答案了。

//C++
#include<bits/locale_facets.h>
#include<stdio.h>
#include<memory.h>
#include<queue>
#define downt(i,n) for(int i=n;i;i=back[i])
#define forto(name,i,d,u) for(name i=d;i<=u;i++)
#define foruntil(name,i,d,u) for(name i=d;i<u;i++)
const int nm=201;
inline void output(long long o); 
inline long long input();
template<int nn,int mm,typename name>struct network{
#define nnn (nn+3)
#define mmmm (mm<<2)+2
    int s,t,tot,nnnn,last[nnn],level[nnn],to[mmmm],arc[mmmm],back[mmmm];
    name c[mmmm];
    std::queue<int>q;
    network(){nnnn=nnn<<2,INIT();}
#undef nnn
#undef mmmm
    void INIT(){tot=1,memset(last,0,nnnn);}
    void add(int f,int t,name cap){to[++tot]=t,c[tot]=cap,back[tot]=last[f],last[f]=tot;}
    void insert(int f,int t,name cap){
        if(cap){
            if(cap<0)std::swap(f,t),cap=-cap;
            add(f,t,cap),add(t,f,0);
        }
    }bool climb(){
        memset(level,0,nnnn),q.push(s),level[s]=0;
        for(int p,too;!q.empty();q.pop()){
            p=q.front(),level[p]++;
            downt(i,last[p])
            if(c[i]&&!level[too=to[i]])level[too]=level[p],q.push(too);
        }return level[t];
    }name augment(int p,name m){
        if(p==t)return m;
        name sum=0,flow;
        int d=level[p]+1;
        for(;arc[p];arc[p]=back[arc[p]])
        if(level[to[arc[p]]]==d&&c[arc[p]]){
            sum+=(flow=augment(to[arc[p]],std::min(c[arc[p]],(name)(m-sum)))),c[arc[p]]-=flow,c[arc[p]^1]+=flow;
            if(sum==m)return m;
        }return sum;
    }name Dinic(name inf){
        name maximum=0;
        while(climb()){
            foruntil(int,i,s,t)arc[i]=last[i];
            maximum+=augment(s,inf);
        }return maximum;
    }
    void new1(short m){
        short n=input(),a,b;
        s=0,t=n+m+1;
        forto(short,i,1,m)insert(0,i,1);
        forto(short,i,m+1,m+n)insert(i,t,1);
        while(true){
            if((a=input())==-1)break;
            insert(a,input(),1);
        }output(Dinic(100)),putchar('\n');
        forto(short,i,1,m)
        for(short j=last[i];back[j];j=back[j])
        if(!c[j])output(i),putchar(' '),output(to[j]),putchar('\n');
    }
};network<200,40000,short>pilot;
int main(){
    pilot.new1(input());
    return 0;
}inline void output(long long o){
    if(o<0)putchar('-'),o=-o;
    if(o>=10)output(o/10);
    putchar(o%10^'0');
}inline long long input(){
    bool minus=false;
    char now=getchar();
    long long i=0;
    for(;!isdigit(now);now=getchar())
    if(now=='-')minus=!minus;
    for(;isdigit(now);now=getchar())i=(i<<3)+(i<<1)+(now^'0');
    return minus?-i:i;
}

题集

希望这些外籍飞行员里能有中国飞行员。

还是中国飞行员强。