zoukankan      html  css  js  c++  java
  • 洛谷 P2756 飞行员配对方案问题 (二分图匹配)

    题目链接:P2756 飞行员配对方案问题

    题意

    给定 (m) 个外籍飞行员和 (n - m) 个英国飞行员,每一架飞机需要一名英国飞行员和一名外籍飞行员,求最多能派出几架飞机。

    思路

    最大流

    二分图最大匹配的模板题。

    建立一个超级源点 (s) 和一个超级汇点 (t)。让 (s) 与所有的外籍飞行员建立有向边,所有的英国飞行员与 (t) 建立有向边。让所有边的容量为 (1),求最大流即可。最后找出所有流量为 (1) 的反向边即可。

    此题也可以使用匈牙利算法。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int N = 500;
    const int M = 1e5 + 10;
    
    int head[N], ver[M], edge[M], Next[M], d[N];
    int tot, maxflow;
    int s, t;
    
    void add(int x, int y, int z) {
        ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
        ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot;
    }
    
    bool bfs() {
        memset(d, 0, sizeof(d));
        queue<int> q;
        q.push(s); d[s] = 1;
        while(q.size()) {
            int x = q.front(); q.pop();
            for(int i = head[x]; i; i = Next[i]) {
                if(edge[i] && !d[ver[i]]) {
                    q.push(ver[i]);
                    d[ver[i]] = d[x] + 1;
                    if(ver[i] == t) return 1;
                }
            }
        }
        return 0;
    }
    
    int dinic(int x, int flow) {
        if(x == t) return flow;
        int rest = flow, k;
        for(int i = head[x]; i && rest; i = Next[i]) {
            if(edge[i] && d[ver[i]] == d[x] + 1) {
                k = dinic(ver[i], min(rest, edge[i]));
                if(!k) d[ver[i]] = 0;
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
            }
        }
        return flow - rest;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n, m;
        cin >> m >> n;
        tot = 1;
        s = 0;
        t = n + 1;
        for(int i = 1; i <= m; ++i) add(s, i, 1);
        for(int i = m + 1; i <= n; ++i) add(i, t, 1);
        int u, v;
        while(cin >> u >> v) {
            if(u == -1 && v == -1) break;
            add(u, v, 1);
        }
        int flow = 0;
        while(bfs()) {
            while(flow = dinic(s, inf)) {
                maxflow += flow;
            }
        }
        if(maxflow == 0) {
            cout << "No Solution!" << endl;
            return 0;
        }
        cout << maxflow << endl;
        for(int i = 1; i <= m; ++i) {
            for(int j = head[i]; j; j = Next[j]) {
                if(ver[j] != s && edge[j] == 0 && edge[j ^ 1] == 1) {
                    cout << i << " " << ver[j] << endl;
                }
            }
        }
        return 0;
    }
    

    参考

    《算法竞赛进阶指南》 李煜东 著

  • 相关阅读:
    linux下mysql区分大小写的内容
    jar包 pom
    项目的考虑
    webservice
    MySQL外键设置中的的 Cascade、NO ACTION、Restrict、SET NULL
    JVM参数最佳实践:元空间的初始大小和最大大小
    JVM问题排查工具:Serviceability-Agent介绍
    Spring Boot 2.x基础教程:构建RESTful API与单元测试
    彻底搞懂JVM类加载器:基本概念
    如何解决90%的问题?10位阿里大牛公布方法
  • 原文地址:https://www.cnblogs.com/wulitaotao/p/11565359.html
Copyright © 2011-2022 走看看