HDU2255

二分图最大匹配基础

详见

这题是最大权二分图匹配模板

讲解

 (小黄书上也是有的,讲解也很清晰)

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
int n,w[302][302],res,match[302],lx[302],ly[302],slack[302];
bool visx[302],visy[302];
inline void read(int &x){
    char ch=getchar();x=0;int f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    x*=f;
}
inline bool dfs(int x){
    visx[x]=true;
    for(int y=1;y<=n;y++){
        if(visy[y])continue;
        int gap=lx[x]+ly[y]-w[x][y];
        if(gap==0){
            visy[y]=true;
            if(match[y]==-1 || dfs(match[y])){
                match[y]=x;return true;
            }
        }else slack[y]=min(slack[y],gap);
    }
    return false;
}
inline void km(){
    memset(match,-1,sizeof match);
    memset(ly,0,sizeof ly);
    for(int i=1;i<=n;i++){
        lx[i]=w[i][1];
        for(int j=2;j<=n;j++)lx[i]=max(lx[i],w[i][j]);
    }
    for(int i=1;i<=n;i++){
        fill(slack,slack+n+1,0x3f3f3f3f);  
        while(1){
            memset(visx,false,sizeof visx);memset(visy,false,sizeof visy);
            if(dfs(i))break;
            int d=0x3f3f3f3f;
            for(int j=1;j<=n;j++)if(!visy[j])d=min(d,slack[j]);
            for(int j=1;j<=n;j++){
                if(visx[j])lx[j]-=d;
                if(visy[j])ly[j]+=d;
                else slack[j]-=d;
            }
        }
    }
}
int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)read(w[i][j]);
        km();
        res=0;for(int i=1;i<=n;i++)res+=w[match[i]][i];
        printf("%d\n",res);
    }
    return 0;
}

 

posted @ 2018-06-13 06:56  lnyzo  阅读(157)  评论(0编辑  收藏  举报