zoukankan      html  css  js  c++  java
  • [网络流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;
    }
    
  • 相关阅读:
    常用查看日志的命令
    通过maven profile配置不同开发环境
    java使用shiro小记
    gitlab使用小记
    java使用guava变形数据结构
    php 把驼峰样式的字符串转换成下划线样式的字符串
    tcp粘包和拆包的处理方案
    php和js中,utf-8编码转成base64编码
    yum的用法
    rpm的用法
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337340.html
Copyright © 2011-2022 走看看