[网络流24题] 飞行员配对方案问题

题意

图片说明

题解

二分图匹配裸题
不过既然是在网络流24题里面..还是不用匈牙利解了吧
建图 设超级源点s,超级汇点t
对于每个外籍飞行员i,连一条s-i流量为1的边
对于每个英国飞行员j,连一条j-t流量为1的边
对与每个给定的配对方案,连一条i-j流量为1的边
直接跑dinic即可,得到最大流就是能派出的飞机个数。

在输出路径时只需要找对于每个外籍飞行员i的边容量是否为0,若为0说明最大流流过了这条边,输出即可。

code

#include <bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define inf 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
#define ios ios::sync_with_stdio(false)
#define rep(i, l, r) for (int i = (l); i < (r); i++)
using namespace std;

const int maxn = 400 + 10;
const int mod = 1e9 + 7;
int n, m;
int s = 0, t = 400 + 1;

struct Edge
{
    int to, cap;
    int nxt;
} edges[maxn * maxn];
int head[maxn], deep[maxn], tot = 0;
int cur[maxn];

void addedge(int from,int to,int cost)
{
    edges[tot].nxt = head[from];
    edges[tot].to = to;
    edges[tot].cap = cost;
    head[from] = tot;
    tot++;
}

bool bfs(int s,int t)
{
    memset(deep,-1,sizeof(deep));
    for(int i = 0;i <= maxn;++i) cur[i] = head[i];
    deep[s] = 0;
    queue<int> que;
    que.push(s);
    while(!que.empty()){
        int v = que.front();
        que.pop();
        for(int i = head[v];i != -1;i = edges[i].nxt){
            Edge &e = edges[i];
            if(e.cap > 0 && deep[e.to] == -1){
                deep[e.to] = deep[v]+1;
                que.push(e.to);
            }
        }
    }
    if(deep[t] == -1) return false;
    return true;
}

int dfs(int v,int t,int f){
    if(!f || v == t) return f;
    int flow = 0,d;
    for(int &i = cur[v];i != -1;i = edges[i].nxt){
        Edge &e = edges[i];
        if(e.cap > 0 && deep[e.to] == deep[v]+1){
            d = dfs(e.to,t,min(e.cap,f));
            flow += d;
            f -= d;
            edges[i].cap -= d;
            edges[i^1].cap += d;
            if(!f) break;
        }
    }
    if(!flow) deep[v] = -2;
    return flow;
}

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

void init(int n)
{
    tot = 0;
    for (int i = 0; i <= n; ++i)
    {
        head[i] = -1;
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    cin >> m >> n;
    init(n);
    for (int i = 1; i <= m; ++i)
    {
        addedge(s, i, 1);
        addedge(i, s, 0);
    }
    for (int i = m + 1; i <= n; ++i)
    {
        addedge(i, t, 1);
        addedge(t, i, 0);
    }
    int u, v;
    while (cin >> u >> v)
    {
        if (u == -1 && v == -1)
            break;
        addedge(u, v, 1);
        addedge(v, u, 0);
    }
    int cnt = Dinic(s, t);
    if (!cnt)
    {
        puts("No Solution!");
        return 0;
    }
    printf("%d\n", cnt);
    for (int u = 1; u <= m; ++u)
    {
        for (int j = head[u]; ~j; j = edges[j].nxt)
        {
            int v = edges[j].to;
            if (v != s && u != s && v != t && edges[j].cap == 0 && edges[j ^ 1].cap == 1)
            {
                printf("%d %d\n", u, v);
            }
        }
    }
    return 0;
}
题解 文章被收录于专栏

竞赛养老选手佛系刷题~

全部评论

相关推荐

Hakasee:我的简历和你的基本一样,上周去了上海,boss投了三百家, 三家线下面试 第一家没有做题,全是八股和项目,因为第一次面试不怎么熟练,挂了 第二家,给你几个题目(①css垂直居中文字,字体每两秒闪烁一下以及点击弹窗,②给你一个链接,实现可视化地图,③然后是八股,图片性能优化,以及对图片app有什么想法),45分钟内做完,然后老板面试) 第三家特别偏僻,有点阴森,到了之后让了一个工位给我,有四个题目,①格式化时间 年月日当前时间星期几② 正则表达式提取新闻文字,③在文本域输入文字生成选择题以及选项④生成商品排版还是什么来着 三家都是不超过50人的小公司 两家线上牛客笔试(卡伦特,七牛云,但是笔试不仅要考前端,还要考后端,算法,甚至数学题 我的建议是如果只做了这两个vue项目且不怎么熟练的情况下,先沉淀沉淀,把react学了,上海好的公司基本都是react查看图片
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务