飞行员配对方案问题

传送门

这道题明显是二分图匹配……(因为我至今不会写匈牙利我就跑了遍dinic)

非常的明显,自己设定一个原点和汇点。把原点向所有的外籍飞行员连容量为1的边,所有的英国飞行员向汇点连容量为1的边,中间的边按题目描述,给你一条你就建一条容量为1的边。

之后直接跑网络流。至于最后怎么判断哪几个飞行员是配对的,直接判断那些连在中间的边,如果其反向边的流量不为0就说明这条边上面有流量,也就说明它被跑过。

反正这题有spj可以直接过。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')

using namespace std;
const int M = 100005;
const int INF = 1e9;
typedef long long ll;

int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
struct edge
{
    int next,to,v,from;
}e[M];

int m,n,head[M],ecnt = -1,deep[M],maxflow,x,y,source,sink,sum,cur[M];
queue <int> q;

void add(int x,int y,int z)
{
    e[++ecnt].to = y;
    e[ecnt].v = z;
    e[ecnt].from = x;
    e[ecnt].next = head[x];
    head[x] = ecnt;
}

bool bfs(int s,int t)
{
    memset(deep,-1,sizeof(deep));
    while(!q.empty()) q.pop();
    rep(i,0,n+1) cur[i] = head[i];
    deep[s] = 0,q.push(s);
    while(!q.empty())
    {
        int k = q.front();q.pop();
        for(int i = head[k];i != -1;i = e[i].next)
        {
            if(deep[e[i].to] == -1 && e[i].v)
            deep[e[i].to] = deep[k] + 1,q.push(e[i].to);
        }
    }
    if(deep[t] == -1) return 0;
    else return 1;
}

int dfs(int s,int t,int limit)
{
    if(!limit || s == t) return limit;
    int flow = 0;
    for(int i = cur[s];i != -1;i = e[i].next)
    {
        cur[s] = i;
        if(deep[e[i].to] != deep[s] + 1) continue;
        int f = dfs(e[i].to,t,min(limit,e[i].v));
        if(f)
        {
            e[i].v -= f,e[i^1].v += f;
            limit -= f,flow += f;
            if(!limit) break;
        }
    }
    if(!flow) deep[s] = -2333333; 
    return flow;
}

void dinic(int s,int t)
{
    while(bfs(s,t)) maxflow += dfs(s,t,INF);
}

int main()
{
    memset(head,-1,sizeof(head));
    m = read(),n = read();
    source = 0,sink = n+1;
    while(1)
    {
        x = read(),y = read();
        if(x == -1 && y == -1) break;
        add(x,y,1),add(y,x,0),sum++;
    }
    rep(i,1,m) add(source,i,1),add(i,source,0);
    rep(i,m+1,n) add(i,sink,1),add(sink,i,0);
    dinic(source,sink);
    if(maxflow)
    {
        printf("%d\n",maxflow);
        for(int i = 0;i <= (sum-1)<<1;i += 2)
        if(e[i^1].v != 0) printf("%d %d\n",e[i].from,e[i].to);
    }
    else printf("No Solution!\n");
    return 0;
}

 

posted @ 2018-08-29 22:39  CaptainLi  阅读(729)  评论(0编辑  收藏  举报