例题5.24 少林决胜 UVa11383

来源:互联网 发布:程序员用的字体 编辑:程序博客网 时间:2024/04/28 01:26

1.题目描述:点击打开链接

2.解题思路:本题是KM算法的副产物,在KM算法中,有一个不等式就是L(x)+L(y)>=w(x,y)。算法结束的时候,所有的顶标之和就是最小的。

3.代码:

#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>//#include<cmath>#include<ctime>#include<cctype>#include<list>#include<complex>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef pair <int,int> P;const int N=500+10;const int INF=1e9;int W[N][N],n;int Lx[N],Ly[N];int Left[N];bool S[N],T[N];bool match(int i){    S[i]=true;    for(int j=1;j<=n;j++)        if(Lx[i]+Ly[j]==W[i][j]&&!T[j])    {        T[j]=true;        if(!Left[j]||match(Left[j]))        {            Left[j]=i;            return true;        }    }    return false;}void update(){    int a=INF;    for(int i=1;i<=n;i++)if(S[i])        for(int j=1;j<=n;j++)if(!T[j])        a=min(a,Lx[i]+Ly[j]-W[i][j]);    for(int i=1;i<=n;i++)    {        if(S[i])Lx[i]-=a;        if(T[i])Ly[i]+=a;    }}void KM(){    for(int i=1;i<=n;i++)    {        Left[i]=Lx[i]=Ly[i]=0;        for(int j=1;j<=n;j++)            Lx[i]=max(Lx[i],W[i][j]);    }    for(int i=1;i<=n;i++)    {        for(;;)        {            for(int j=1;j<=n;j++)                S[j]=T[j]=0;            if(match(i))break;            else update();        }    }}int main(){    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            scanf("%d",&W[i][j]);        KM();        int sum=0;        for(int i=1;i<n;i++)        {            printf("%d ",Lx[i]);            sum+=Lx[i];        }        printf("%d\n",Lx[n]);        for(int i=1;i<n;i++)        {            printf("%d ",Ly[i]);            sum+=Ly[i];        }        printf("%d\n",Ly[n]);        printf("%d\n",sum+Lx[n]+Ly[n]);    }}


0 0