• KM算法(二分图最大权匹配)


    #include <bits/stdc++.h>
    #define N 1500
    #define inf 999999999
    using namespace std;
    int a[N],bs[N],nx=0,ny=0,k;
    int linky[N],lx[N],ly[N],slack[N];
    int visx[N],visy[N],w[N][N];
    int min(int a,int b){return (a<b)?a:b;}
    int find(int x){
        visx[x]=1;
        for(int y=1;y<=ny;y++){
            if(visy[y]) continue;
            int t=lx[x]+ly[y]-w[x][y];
            if(t==0){visy[y]=1;
                if(linky[y]==-1||find(linky[y])){
                    linky[y]=x;return 1;
                }
            }
            else if(slack[y]>t) slack[y]=t;
        }
        return 0;
    }
    int km(){
        memset(linky,-1,sizeof(linky));
        memset(ly,0,sizeof(ly));
        for(int i=1;i<=nx;i++) lx[i]=-inf;
        for(int i=1;i<=nx;i++)for(int j=1;j<=ny;j++)if(w[i][j]>lx[i])lx[i]=w[i][j];
        for(int x=1;x<=nx;x++){
            for(int i=1;i<=ny;i++)
                slack[i]=inf;
            while(1){
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(find(x)) break;
                int d=inf;
                for(int i=1;i<=ny;i++) if(!visy[i]&&d>slack[i]) d=slack[i];
                for(int i=1;i<=nx;i++) if(visx[i]) lx[i]-=d;
                for(int i=1;i<=ny;i++) if(visy[i]) ly[i]+=d; else slack[i]-=d;
            }
        }
        int result=0;
        for(int i=1;i<=ny;i++)
        if(linky[i]>-1) result+=w[linky[i]][i];
        return result;
    }
    int main(){
        scanf("%d%d%d",&nx,&ny,&k);
        for(int i=1;i<=k;i++){
            int a,b,c;scanf("%d%d%d",&a,&b,&c);
            w[a][b]=c;
        }printf("%d
    ",km());
        return 0;
    }
    rush!
  • 相关阅读:
    排列 [计数dp]
    排列 [计数dp]
    函数 [计数]
    多态
    继承2
    2018年蓝桥杯b组国赛真题
    c++的继承
    运算符2
    运算符重载
    拷贝构造
  • 原文地址:https://www.cnblogs.com/LH2000/p/14152226.html
Copyright © 2020-2023  润新知