UVA 11383 Golden Tiger Claw

来源:互联网 发布:打击电信网络诈骗视频 编辑:程序博客网 时间:2024/06/05 19:42

UVA 11383 Golden Tiger Claw

带权二分图最大完美匹配,深入理解KM算法

题意

题意:给一个n*n的矩阵,每个格子中有正整数w[i][j],试为每行和每列分别确定一个数字row[i]和col[i],使得任意格子w[i][j]<=row[i]+col[j]恒成立。先输row,再输出col,再输出全部总和(总和应尽量小)。

思路

利用KM算法中的l(x)+l(y)>=w(x,y)。算法结束后所有标顶之和是最小的。即所求答案。
见训练指南P351

代码

#include<bits/stdc++.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN=507;const int oo=0x3f3f3f3f;typedef long long LL;int w[MAXN][MAXN],x[MAXN],slack[MAXN],y[MAXN];int prev_x[MAXN],prev_y[MAXN],son_y[MAXN],par[MAXN];int lx,ly,pop;///w表示带权图///pop表示一侧点数///返回最大完美匹配权值///son_y表示匹配方案void adjust(int v){    son_y[v]=prev_y[v];    if(prev_x[son_y[v]]!=-2)        adjust(prev_x[son_y[v]]);}bool fin_d(int v){    for(int i=1; i<=pop; i++)    {        if(prev_y[i]==-1)        {            if(slack[i]>x[v]+y[i]-w[v][i])            {                slack[i]=x[v]+y[i]-w[v][i];                par[i]=v;            }            if(x[v]+y[i]==w[v][i])            {                prev_y[i]=v;                if(son_y[i]==-1)                {                    adjust(i);                    return true;                }                if(prev_x[son_y[i]]!=-1) continue;                prev_x[son_y[i]]=i;                if(fin_d(son_y[i])) return true;            }        }    }    return false;}int KM(){    int m=0;    for(int i=1; i<=pop; i++)    {        son_y[i]=-1;        y[i]=0;    }    for(int i=1; i<=pop; i++)    {        x[i]=0;        for(int j=1; j<=pop; j++)            x[i]=max(x[i],w[i][j]);    }    bool flag;    for(int i=1; i<=pop; i++)    {        for(int j=1; j<=pop; j++)        {            prev_x[j]=prev_y[j]=-1;            slack[j]=oo;        }        prev_x[i]=-2;        if(fin_d(i)) continue;        flag=false;        while(!flag)        {            m=oo;            for(int j=1; j<=pop; j++)            {                if(prev_y[j]==-1)                    m=min(m,slack[j]);            }            for(int j=1; j<=pop; j++)            {                if(prev_x[j]!=-1)                    x[j]-=m;                if(prev_y[j]!=-1)                    y[j]+=m;                else slack[j]-=m;            }            for(int j=1; j<=pop; j++)            {                if(prev_y[j]==-1&&!slack[j])                {                    prev_y[j]=par[j];                    if(son_y[j]==-1)                    {                        adjust(j);                        flag=true;                        break;                    }                    prev_x[son_y[j]]=j;                    if(fin_d(son_y[j]))                    {                        flag=true;                        break;                    }                }            }        }    }    int ans=0;    for(int i=1; i<=pop; i++)        ans+=w[son_y[i]][i];    return ans;}int main(){    int n;    while(scanf("%d",&n)==1)    {        for(int i=1; i<=n; i++)            for(int j=1; j<=n; j++)            {                scanf("%d",&w[i][j]);            }        pop=n;        int res=KM();        for(int i=1;i<=n;i++) printf("%d%c",x[i],i==n?'\n':' ');        for(int i=1;i<=n;i++) printf("%d%c",y[i],i==n?'\n':' ');        printf("%d\n",res);    }    return 0;}
阅读全文
0 0
原创粉丝点击