zoukankan      html  css  js  c++  java
  • 牛客网暑期ACM多校训练营(第五场) E room(最小费用最大流 , 最小权二分图匹配模板)

    链接:

    https://www.nowcoder.com/acm/contest/143/E

    题意:

    给定n个宿舍的新安排, 每个宿舍都有4个人, 问要至少有多少个人换位才能变成新安排。

    可以建一个二分图, 左边n个点为原来的安排, 右边n个点为新安排,  每条边花费设为( 4 - 交集), 然后跑费用流。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxN = 300;
    const int maxM = 1e5 + 7;
    const int INF = 1e9 + 7;
    int n, ecnt, S, T;
    struct {
        int to, w, cost, nxt;
    } edge[maxM];
     
    struct Node{
        int v, id;
    }pre[maxN];
    int head[maxN];
    int bef[maxN][4], after[maxN][4];
     
     
    void init() {
        memset(head, -1, sizeof(head));
        ecnt = 0;
    }
    void addEdge(int u, int v, int w, int c) {
        edge[ecnt].to = v;
        edge[ecnt].w = w;
        edge[ecnt].cost = c;
        edge[ecnt].nxt = head[u];
        head[u] = ecnt++;
    }
    inline int dif(int a, int b) {
        int res = 4;
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                if(bef[a][i] == after[b][j]) {
                    res--;
                    break;
                }
            }
        }
        return res;
    }
    void build() {
        S = 0, T = 2 * n + 1;
     
        for(int i = 1; i <= n; i++) {
            addEdge(S, i, 1, 0);
            addEdge(i, S, 0, 0);
            addEdge(i + n, T, 1, 0);
            addEdge(T, i + n, 0, 0);
        }
     
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                int c = dif(i, j);
                addEdge(i, j + n, 1, c);
                addEdge(j + n, i, 0, -c); //建反向边的时候注意花费要为负
            }
        }
    }
    int vis[maxN], cost[maxN];
    bool spfa(){
        queue<int> q;
        memset(vis, 0, sizeof(vis));
        fill(cost ,cost + maxN, INF);
        vis[S] = 1;
        cost[S] = 0;
        q.push(S);
        while(!q.empty()){
            int u = q.front();
            for(int i = head[u]; i != -1; i = edge[i].nxt){
                int v = edge[i].to, f = edge[i].w , c = edge[i].cost;
                if(f == 0 || cost[v] <= cost[u] + c) continue;
                cost[v] = cost[u] + c;
                pre[v].v = u;
                pre[v].id = i;
                if(!vis[v]){
                    q.push(v);
                    vis[v] = true;
                }
            }
            vis[u] = 0;
            q.pop();
        }
        return cost[T] != INF;
    }
    int MCMF(){
        int flow = 0;
        int minCost = 0;
        while(spfa()){
            int minFlow = INF;
            for(int i = T; i != S; i = pre[i].v){
                minFlow = min(minFlow, edge[pre[i].id].w);
            }
            for(int i = T; i != S; i = pre[i].v){
                edge[pre[i].id].w -= minFlow;
                edge[pre[i].id ^ 1].w += minFlow;
            }
            minCost += cost[T];
        }
        return minCost;
    }
    int main() {
    //    freopen("1.txt","r", stdin);
        ios::sync_with_stdio(false);
     
        cin >> n;
        init();
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < 4; j++)
                cin >> bef[i][j];
     
     
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < 4; j++)
                cin >> after[i][j];
     
        build();
        cout << MCMF() << "
    ";
    }
  • 相关阅读:
    hdu多校4
    hdu多校第三场
    牛客多校4
    bzoj 1477 扩展欧几里德
    bzoj 1485 卡特兰数 + 分解因子
    hdu多校 2
    牛客网暑期多校2
    bzoj 1040 基向内环树dp
    hdu 多校第一场
    SPOJ
  • 原文地址:https://www.cnblogs.com/Jadon97/p/9426420.html
Copyright © 2011-2022 走看看