• 二分图最佳匹配


    由于最大匹配有很多 毒瘤的出题人就想到给每条边加个权然后整一个权值最大

    于是喜提最佳匹配

    大佬的blog真的好 彻底明白了 传送门

    这个问题主要是基于完全图匹配的

    如果不是完全图就补一个价值为0就行

    算法中就是这两个点用了但是没有产生价值

    一定比不选还要差...

    算法主要流程:

    1.找到左部图中的待匹配顶点

    2.直接去右部图匹配

    3.如果右部图没有匹配点 就更改label(类似于网络流的增广路)

    4.循环2,3直到找到匹配为止

    Code:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<iostream>
    #include<iomanip>
    #define itn int
    #define ms(a,b) memset(a,b,sizeof a)
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define inf 2147483647
    using namespace std;
    typedef long long ll;
    ll read() {
        ll as = 0,fu = 1;
        char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') fu = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            as = as * 10 + c - '0';
            c = getchar();
        }
        return as * fu;
    }
    //head
    const int N = 3006;
    int n,ans; 
    int v[N][N];
    int match[N];
    int visx[N],visy[N];
    int lx[N],ly[N];//label
    
    bool dfs(int x) {
        visx[x] = 1;
        rep(y,1,n) {
            if(!visy[x] || (lx[x] + ly[y] == v[x][y])) {
                visy[y] = 1;
                if(!match[y] || dfs(match[y])) {
                    match[y] = x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    void init() {
        ms(lx,0),ms(ly,0),ms(v,0);
        ms(match,0);    
    }
    
    void solve() {
        init();
        rep(i,1,n) {
            rep(j,1,n) v[i][j] = read();
            int tmp = 0;
            rep(j,1,n) tmp = max(tmp,v[i][j]);
            lx[i] = tmp;
        }
        rep(i,1,n) {
            while(1) {
                int d = inf;
                ms(visx,0),ms(visy,0);
                if(dfs(i)) break;
                rep(j,1,n) {
                    if(!visx[j]) continue;
                    rep(k,1,n) if(!visy[k]) d = min(d,lx[j] + ly[k] - v[j][k]);
                }
                if(d == inf) {
                    puts("-1");
                    return;
                }
                rep(j,1,n) if(visx[j]) lx[j] -= d;
                rep(k,1,n) if(visy[k]) ly[k] += d;
            }
        }
        ans = 0;
        rep(i,1,n) ans += v[match[i]][i];
        printf("%d
    ",ans);
    }
    
    
    int main() {
        while(~scanf("%d",&n)) solve();
        return 0;
    }
    > 别忘了 总有人在等着你
  • 相关阅读:
    Windows Live Writer介绍及相关问题解决
    阳光盒子火狐浏览器
    Cracking Wifi Wpa-Wpa2 in 5 second——Dumpper V.80.8 +JumpStart+WinPcap
    叮咚recovery——想刷什么包就刷什么包
    vivo s11t线刷救砖过程
    syskey——让你的电脑更加安全
    滑动关机
    QQ空间点赞大法+浏览器自动翻页脚本=点赞根本停不下来
    Kon-boot v2.5介绍与使用方法总结(支持win10)
    Mimikatz的使用心得
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9925450.html
Copyright © 2020-2023  润新知