LibreOJ 6000 搭配飞行员(最大流)

题解:最基础的最大流,按照主飞行员与起点建边,副飞行员与终点建边,可以同坐的主副飞行员之间建边,值均为一,然后跑一边最大流就完美了!

代码如下:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;

int head[10010],next[10010],v[10010],w[10010],deep[10010];
int s,t,cnt;

void init()
{
    cnt=-1;
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));
}

void add(int from,int to,int cost)
{
    cnt++;
    next[cnt]=head[from];
    v[cnt]=to;
    w[cnt]=cost;
    head[from]=cnt;
}

void add_edge(int from,int to,int cost)
{
    add(from,to,cost);
    add(to,from,0);
}

int bfs(int s,int t)
{
    queue<int> q;
    memset(deep,0,sizeof(deep));
    deep[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=next[i])
        {
            if(w[i]>0&&(!deep[v[i]]))
            {
                deep[v[i]]=deep[u]+1;
                q.push(v[i]);
            }
        }
    }
    if(!deep[t])
    {
        return 0;
    }
    return 1;
}

int dfs(int u,int t,int dist)
{
    if(u==t)
    {
        return dist;
    }
    for(int i=head[u];i!=-1;i=next[i])
    {
        if((deep[v[i]]==deep[u]+1)&&w[i])
        {
            int di=dfs(v[i],t,min(w[i],dist));
            if(di>0)
            {
                w[i]-=di;
                w[i^1]+=di;
                return di;
            }
        }
    }
    return 0;
}

int dinic(int s,int t)
{
    int res=0;
    while(bfs(s,t))
    {
        while(int d=dfs(s,t,inf))
        {
            res+=d;
        }
    }
    return res;
}

int main()
{
    int n,m;
    init();
    scanf("%d%d",&n,&m);
    s=0;t=n+1;
    for(int i=1;i<=m;i++)
    {
        add_edge(s,i,1);
    }
    for(int i=m+1;i<=n;i++)
    {
        add_edge(i,t,1);
    }
    int x,y;
    while(scanf("%d%d",&x,&y)!=EOF)
    {
        add_edge(x,y,1);
    }
    int ans=dinic(s,t);
    printf("%d\n",ans);
}

 

posted @ 2018-03-14 20:44  Styx-ferryman  阅读(181)  评论(0编辑  收藏  举报