【UVA11383】 Golden Tiger Claw 【二分图KM算法(板子)】

题目

题目传送门:https://www.luogu.com.cn/problem/UVA11383

分析

最近刚刚学了二分图,然后来了一个这样的题,看完题意之后,稍微想一想就能想出来是一个二分图,然后就是裸的板子解决。没什么难的。

代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
const int maxn=1e3+10;
const int Inf=0x3f3f3f3f;
ll n,mi;
ll x[maxn],y[maxn],w[maxn][maxn],mat[maxn];
bool S[maxn],T[maxn];
bool Match(ll u){
    S[u]=true;
    for(ll i=1;i<=n;++i){
        if(!T[i]){
            ll tmp(x[u]+y[i]-w[u][i]);
            if(!tmp){
                T[i]=true;
                if(!mat[i] || Match(mat[i])){
                    mat[i]=u;
                    return true;
                }
            }
            else
                mi=min(mi,tmp);
        }
    }return false;
}
void Update(){
    for(ll i=1;i<=n;++i)
        if(S[i]) x[i]-=mi;
    for(ll i=1;i<=n;++i)
        if(T[i]) y[i]+=mi;
}
void KM(){
    for(ll i=1;i<=n;++i){
        mat[i]=x[i]=y[i]=0;
        for(ll j=1;j<=n;++j)
            x[i]=max(x[i],w[i][j]);
    }
    for(ll i=1;i<=n;++i){
        while(true){
            for(ll i=1;i<=n;++i)
                S[i]=T[i]=false;
            mi=Inf;
            if(Match(i)) break;
            else Update();
        }
    }
}
int main(){
    while(scanf("%d",&n)!=EOF&&n){
        for(ll i=1;i<=n;++i)
            for(ll j=1;j<=n;++j)
                scanf("%d",&w[i][j]);
        KM();
        ll ans=0;
        for(ll i=1;i<=n;++i)
            ans+=x[i];
        for(ll i=1;i<=n;++i)
            ans+=y[i];
            
        printf("%d",x[1]);
        for(ll i=2;i<=n;++i)
            printf(" %d",x[i]);printf("\n");
        printf("%d",y[1]);
        for(ll i=2;i<=n;++i)
            printf(" %d ",y[i]);printf("\n");
            
        printf("%d\n",ans);
    }return 0;
}

 

posted @ 2020-05-11 17:08  Vocanda  阅读(205)  评论(0编辑  收藏  举报