zoukankan      html  css  js  c++  java
  • 【网络流24题】 1. 飞行员配对问题 题解

    题目链接(洛谷 P2756)

    题意:

    一共有(n)个飞行员,其中有(m)个外籍飞行员和(n - m)个英国飞行员,外籍飞行员从(1)(m)编号英国飞行员从 (m + 1)(n)编号。 对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    思路:

    二分图匹配板题。用匈牙利算法输出匹配会比较方便,而且代码比较短。用网络流的话,给左右两侧的点分别连一条容量为(1)的边,建立一个超级源和超级汇点即可。

    代码:

    匈牙利算法:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 105;
    
    struct Edge {
        int to, nxt;
    }e[maxn * maxn];
    
    int n, m, head[maxn], numedge, match[maxn], vis[maxn], x, y, ans;
    inline void AddEdge(int from, int to) {
        e[numedge].to = to;
        e[numedge].nxt = head[from];
        head[from] = numedge;
        numedge++;
    }
    
    bool dfs(int u, int tag) {
        if (vis[u] == tag) return false;
        vis[u] = tag;
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int to = e[i].to;
            if (!match[to] || dfs(match[to], tag)) {
                match[to] = u;
                return true;
            }
        }
        return false;
    }
    
    int main() {
        memset(head, -1, sizeof(head));
        scanf("%d%d", &m, &n);
        while (scanf("%d%d", &x, &y)) {
            if (x == -1 && y == -1) break;
            AddEdge(x, y);
        }
        for (int i = 1; i <= m; i++) {
            if (dfs(i, i)) ans++;
        }
        printf("%d
    ", ans);
        for (int i = m + 1; i <= n; i++)
            if (match[i]) {
                printf("%d %d
    ", match[i], i);
            }
        return 0;
    }
    

    Dinic算法:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define root 0
    #define target 104
    
    using namespace std;
    const int maxn = 105;
    const int INF = 0x3f3f3f3f;
    
    struct Edge {
        int to, val, nxt;
    }e[maxn * maxn * 2];
    int numedge, head[maxn], ans, n, m, x, y, depth[maxn];
    
    inline void AddEdge(int from, int to, int val) {
        e[numedge].to = to;
        e[numedge].val = val;
        e[numedge].nxt = head[from];
        head[from] = numedge;
        numedge++;
    }
    
    bool bfs() {
        memset(depth, 0, sizeof(depth));
        depth[root] = 1;
        queue<int> q;
        q.push(root);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = e[i].nxt) {
                int to = e[i].to;
                if (e[i].val > 0 && !depth[to]) {
                    depth[to] = depth[u] + 1;
                    q.push(to);
                }
            }
        }
        return depth[target] != 0;
    }
    
    int dfs(int u, int flow) {
        if (u == target) return flow;
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int to = e[i].to;
            if (e[i].val > 0 && depth[to] > depth[u]) {
                int di = dfs(to, min(flow, e[i].val));
                if (di > 0) {
                    e[i].val -= di;
                    e[i ^ 1].val += di;
                    return di;
                }
            }
        }
        return 0;
    }
    
    inline void Dinic() {
        ans = 0;
        while (bfs()) {
            int d;
            while (d = dfs(root, INF)) {
                ans += d;
            }
        }
    }
    
    int main() {
        memset(head, -1, sizeof(head));
        scanf("%d%d", &m, &n);
        while (scanf("%d%d", &x, &y)) {
            if (x == -1 && y == -1) break;
            AddEdge(x, y, 1);
            AddEdge(y, x, 0);
        }
        for (int i = 1; i <= m; i++) {
            AddEdge(root, i, 1);
            AddEdge(i, root, 0);
        }
        for (int i = m + 1; i <= n; i++) {
            AddEdge(i, target, 1);
            AddEdge(target, i, 0);
        }
        Dinic();
        printf("%d
    ", ans);
        for (int i = 1; i <= m; i++) {
            for (int j = head[i]; ~j; j = e[j].nxt) {
                int to = e[j].to;
                if (to == root) continue;
                if (!e[j].val) {
                    printf("%d %d
    ", i, to);
                    break;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    C#利用反射动态调用类及方法
    系统程序监控软件
    SQL server 2008 安装和远程访问的问题
    sql server 创建临时表
    IIS 时间问题
    windows 2008 安装 sql server 2008
    sql server xml nodes 的使用
    Window 7sp1 安装vs2010 sp1 打开xaml文件崩溃
    CSS资源网址
    Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0
  • 原文地址:https://www.cnblogs.com/icysky/p/13605159.html
Copyright © 2011-2022 走看看