• [网络流24题] 分配问题 (二分图的最佳匹配)


    题目链接

    题目很简单,就是要求一个二分图的二分匹配
    数据范围不大,可以用KM算法,也可以用费用流

    #include <bits/stdc++.h>
    const int maxn = 105;
    const int inf = 0x3f3f3f3f;
    using namespace std;
    typedef long long ll;
    struct note{
        int u, v, w, cost;
        int next;
    } e1[maxn * maxn * 2], e2[maxn * maxn * 2];
    int head[maxn << 1], cnt;	//两个图可以共用一个head[]数组,减少代码量
    int n, s, t;
    
    void add(int u, int v, int w, int c){
        e1[cnt] = (note){u, v, w, c, head[u]};
        e2[cnt] = (note){u, v, w, -c, head[u]};
        head[u] = cnt++;
        e1[cnt] = (note){v, u, 0, -c, head[v]};
        e2[cnt] = (note){v, u, 0, c, head[v]};
        head[v] = cnt++;
    }
    bool vis[maxn<<1];
    int flow[maxn << 1], cost[maxn << 1], pre[maxn << 1], last[maxn << 1];
    
    bool spfa(note e[]){
        for (int i = s; i<=t; i++){
            cost[i] = flow[i] = inf;
            vis[i] = false;
        }
        cost[s] = 0;
        pre[t] = -1;
        queue<int> q;
        q.push(s);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            for (int i = head[u]; ~i; i=e[i].next){
                int v = e[i].v, w = e[i].w, c = e[i].cost;
                if(w > 0 && cost[v] > cost[u] + c){
                    cost[v] = cost[u] + c;
                    pre[v] = u, last[v] = i;
                    flow[v] = min(flow[u], w);
                    if(!vis[v]){
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    int mincost;
    int MCMF(note e[]){
        while(spfa(e)){
            mincost += flow[t] * cost[t];
            int now = t;
            while(now != s){
                e[last[now]].w -= flow[t];
                e[last[now] ^ 1].w += flow[t];
                now = pre[now];
            }
        }
        return mincost;
    }
    
    int main()
    {
        scanf("%d", &n);
        memset(head, -1, sizeof(head));
        s = 0, t = 2 * n + 1;
        for (int i = 1; i <= n; i++){
            add(s, i, 1, 0), add(i + n, t, 1, 0);
            for (int j = 1; j <= n; j++){
                int w;
                scanf("%d", &w);
                add(i, j + n, 1, w);
            }
        }
        printf("%d
    ", MCMF(e1));
        mincost = 0;
        printf("%d
    ", -MCMF(e2));
        return 0;
    }
    
  • 相关阅读:
    Linux 创建sftp用户并限制目录权限
    idea操作maven时控制台中文显示乱码/maven项目启动方式
    Docker 容器镜像删除
    Golang 在 Mac、Linux、Windows 下如何交叉编译
    Linux后台运行Jar方法
    MAC安装JDK及环境变量配置
    Docker 容器镜像删除
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
    《设计模式之禅》之状态模式
    《设计模式之禅》之访问者模式
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337340.html
Copyright © 2020-2023  润新知