• P2756 飞行员配对方案问题


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

    题意

    一共有 n n n 个飞行员,其中有 m m m 个外籍飞行员和 ( n − m ) (n - m) (nm) 个英国飞行员,外籍飞行员从 1 1 1 m m m 编号,英国飞行员从 m + 1 m + 1 m+1 n n n 编号。 对于给定的外籍飞行员与英国飞行员的配合情况,找到最大匹配数,并输出所有成功匹配的成对飞行员编号。

    解析

    匹配问题之一,典型的二分图最大匹配问题,这里我们考虑用网络流解。
    我们定义一条边的流量为 1 1 1就是能匹配,那么最终流到终点的流量就是最大匹配数。
    0 0 0号节点与所有外籍飞行员建一条流量为 1 1 1的边
    所有英国飞行员与 n + 1 n + 1 n+1号节点建一条流量为 1 1 1的边
    再根据题所给的外籍飞行员与英国飞行员建流量为 1 1 1的边
    0 0 0号节点到 n + 1 n + 1 n+1号节点的最大流量即为最大匹配数,所有正向边中流量变成 0 0 0的边为匹配上的一对(原本为 1 1 1代表能匹配,若匹配上等于有一个容量为 1 1 1的流经过,会使得边容量 − 1 -1 1,此时容量就为 0 0 0了)

    代码

    使用Dinic算法解题

    #include 
    #include 
    #include 
    using namespace std;
    const int N = 110, M = 10010;
    struct edge{
        int to,nex,w;
    }e[M * 2];
    int n,m,head[N],tot = 1;
    void add(int to,int from,int w){
        e[++ tot].w = w;
        e[tot].to = to;
        e[tot].nex = head[from];
        head[from] = tot;
    }
    
    int dep[N];
    bool bfs()
    {
        queue<int>q;
        q.push(0);
        for(int i = 1; i <= n + 1; i ++) dep[i] = 0;
        dep[0] = 1;
        while(!q.empty()){
            int u = q.front(); q.pop();
            for(int i = head[u]; i; i = e[i].nex){
                int v = e[i].to;
                if(e[i].w && !dep[v]){
                    dep[v] = dep[u] + 1;
                    if(v == n + 1) return true;
                    q.push(v);
                }
            }
        }
        return dep[n + 1];
    }
    
    int dfs(int u, int inflow)
    {
        if(u == n + 1)
            return inflow;
        int outflow = 0;
        for(int i = head[u]; i && inflow; i = e[i].nex){
            int v = e[i].to;
            if(e[i].w && dep[v] == dep[u] + 1){
                int flow = dfs(v, min(e[i].w, inflow));
                e[i].w -= flow;
                e[i ^ 1].w += flow;
                inflow -= flow;
                outflow += flow;
            }
        }
        if(outflow == 0) dep[u] = 0;
        return outflow;
    }
    
    int main()
    {
        scanf("%d%d",&m,&n);
        int u,v;
        for(int i = 1; i <= m; i ++){
            add(0, i, 0);
            add(i, 0, 1);
        }
        for(int i = m + 1; i <= n; i ++){
            add(i, n + 1, 0);
            add(n + 1, i, 1);
        }
        while(scanf("%d%d",&u,&v) != EOF){
            if(u == -1 && v == -1) break; 
            if(u > v) swap(u, v);
            add(u, v, 0);
            add(v, u, 1);
        }
    
        int sum = 0;
        while(bfs()){
            sum += dfs(0, 10000);
        }
        printf("%d\n",sum);
        for(int i = 1; i <= m; i ++){
            for(int j = head[i]; j; j = e[j].nex){
                if(!e[j].w && e[j].to) printf("%d %d\n",i, e[j].to);
            }
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    网络流练习题题单及题解:网络流练习题单

  • 相关阅读:
    java-php-python--损失赔偿保险的客户情况登记及管理-计算机毕业设计
    【动态规划】leetcode 343. 整数拆分
    图的遍历(BFS、DFS)
    Spring之注解开发
    如何在Linux系统中搭建Zookeeper集群
    大数据培训企业开发案例实时读取目录文件到HDFS案例
    Ubuntu 18.04/20.04 LTS 操作系统设置静态DNS
    Spark学习记录1--简介与部署
    灵魂拷问:Mybatis中 Dao接口和XML文件的SQL如何建立关联?
    上传本地包到私有maven仓库
  • 原文地址:https://blog.csdn.net/TT6899911/article/details/127910354