Loading

Golden Tiger Claw(二分图)

Golden Tiger Claw

题意

找到和最小的两个序列a,b满足对于任意i,j有a[i]+b[j]>=c[i][j](矩阵c给出)。

solution

裸的二分图就水过了……

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define clr(a,m) memset(a,m,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

const int MAXN=555;
const int INF =1e9;
const double eps=1e-10;

int gap[MAXN][MAXN];
int Lx[MAXN],Ly[MAXN],slack[MAXN];
int left[MAXN],n;
bool S[MAXN],T[MAXN];

void read()
{
    rep(i,1,n)
        rep(j,1,n)
            scanf("%d",&gap[i][j]);
}

bool match(int u)
{
    S[u]=true;
    rep(v,1,n)
        if(!T[v]){
            int tmp=Lx[u]+Ly[v]-gap[u][v];
            if(tmp==0){
                T[v]=true;
                if(!left[v]||match(left[v])){
                    left[v]=u;
                    return true;
                }
            }else slack[v]=min(slack[v],tmp);
        }
    return false;
}

void update()
{
    int a=INF;
    rep(v,1,n)
        if(!T[v])
            a=min(a,slack[v]);
    rep(i,1,n){
        if(S[i])Lx[i]-=a;
        if(T[i])Ly[i]+=a;
    }
}

void KM()
{
    rep(i,1,n){
        left[i]=Ly[i]=0;
        Lx[i]=-INF;
        rep(j,1,n)
            Lx[i]=max(Lx[i],gap[i][j]);
    }
    rep(i,1,n){
        rep(j,1,n)
            slack[j]=INF;
        while(1)
        {
            rep(j,1,n)
                S[j]=T[j]=0;
            if(match(i))
                break;
            else
                update();
        }
    }
}

void print()
{
    int ans=0;
    rep(i,1,n){
        ans+=Lx[i];
        if(i!=1)printf(" ");
        printf("%d",Lx[i]);

    }
    printf("\n");
    rep(i,1,n){
        ans+=Ly[i];
        if(i!=1)printf(" ");
        printf("%d",Ly[i]);
    }
    printf("\n");
    printf("%d\n",ans);
}

int main()
{
    while(~scanf("%d",&n))
    {
        read();
        KM();
        print();
    }
    return 0;
}
posted @ 2020-05-11 18:10  Gary_818  阅读(141)  评论(0编辑  收藏  举报