【网络流24题】搭配飞行员 | 二分图模型与网络流的转换

题目大意:

给出n个驾驶员,其中m个为正驾驶员,每架飞机需要一个正驾驶和一个副驾驶,正驾驶给出自己满意的副驾驶

那么最多可以起飞多少架飞机?

题目思路:

把正、副驾驶都抽象为一个点,那么如果可以合作(满意)就连一条边,也就转换成了二分图模型

现在把二分图转换为网络流:

1.将所有的副驾驶流向汇点,流量为(1) 

2.将源点流向所有的正驾驶,流量为(1)

3.合法要求间流量随便给,毕竟总流量已经确定了

在这个图上跑最大流 就是我们熟知的二分图的最大匹配了~

Code:

/*** keep hungry and calm CoolGuang!***/
ll n,m,p;
struct Dinic{
    ll cnt = 2;
    struct Edge{
    int e,next;
    ll w;
    };
    int _S,_T,N;
    int head[maxn],d[maxn],cur[maxn];
    Edge edge[maxn];
    void _inint(int s,int t,int n){///n包括S与T
        memset(head,0,sizeof(head));
        cnt = 2;
        _S = s,_T = t,N = n;
    }
    void addedge(int u,int v,ll w){
        edge[cnt] = Edge{v,head[u],w};
        head[u] = cnt++;
    }
    void Add(int u,int v,ll w){
        addedge(u,v,w);addedge(v,u,0);
        ///输出建图 用于debug 一般情况注释
        //printf("%c %lld=[%d %d]%c\n",u==_S?'S':' ',w,u,v,v==_T?'T':' ');
    }
    bool bfs(){
        for(int k=0;k<=N;k++) d[k] = 0;
        queueq;q.push(_S);d[_S] = 1;
        while(!q.empty()){
            int u = q.front();q.pop();
            for(int i=head[u];i;i=edge[i].next){
                int e = edge[i].e;
                if(edge[i].w <= 0||d[e]) continue;
                d[e] = d[u]+1;
                q.push(e);
            }
        }
        for(int k=0;k<=N;k++) cur[k] = head[k];
        return (d[_T] != 0);
    }
    ll dfs(int u,ll flow){
        if(u == _T)return flow;///找到可行流
        for(int &i=cur[u];i;i=edge[i].next){
            int e = edge[i].e;
            if(d[e]!=d[u]+1||edge[i].w<=0) continue;
            ll temp = dfs(e,min(flow,edge[i].w));
            if(temp<=0) continue;
            edge[i].w -= temp;
            edge[i^1].w += temp;
            return temp;
        }
        return 0;
    }
    ll MaxFlow(){
        ll maxflow = 0,delta = 0;
        while(bfs()){
            while(delta = dfs(_S,INF)) maxflow+= delta;
        }return maxflow;
    }
}g;
int main(){
    read(n);read(m);
    g._inint(0,n+1,n+1);
    ll x,y;
    while(scanf("%lld%lld",&x,&y)!=EOF) g.Add(x,y,1);
    for(int i=1;i<=m;i++) g.Add(0,i,1);
    for(int i=m+1;i<=n;i++) g.Add(i,n+1,1);
    printf("%lld\n",g.MaxFlow());
    return 0;
}

 

你可能感兴趣的:(网络流24题,网络流,二分图)