UVA 11383 Golden Tiger Claw(最佳二分图完美匹配)

题意:在一个N*N的方格中,各有一个整数w(i,j),现在要求给每行构造row(i),给每列构造col(j),使得任意w(i,j)<=row(i)+col(j),输出row(i)与col(j)之和最小的方案。

当看到w(i,j)<=row(i)+col(j),并且row()col()都是自己构造的时候,就想到了二分匹配:w[i,j]<=Lx[i]+Ly[j]。直接套用模板,求最佳二分完美匹配,输出Lx[],Ly[],以及最小值即可。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<algorithm>
  5 #define clr(a,m) memset(a,m,sizeof(a))
  6 #define rep(i,a,b) for(int i=a;i<=b;i++)
  7 using namespace std;
  8 
  9 const int MAXN=555;
 10 const int INF =1e9;
 11 const double eps=1e-10;
 12 
 13 int gap[MAXN][MAXN];
 14 int Lx[MAXN],Ly[MAXN],slack[MAXN];
 15 int left[MAXN],n;
 16 bool S[MAXN],T[MAXN];
 17 
 18 void read()
 19 {
 20     rep(i,1,n)
 21         rep(j,1,n)
 22             scanf("%d",&gap[i][j]);
 23 }
 24 
 25 bool match(int u)
 26 {
 27     S[u]=true;
 28     rep(v,1,n)
 29         if(!T[v]){
 30             int tmp=Lx[u]+Ly[v]-gap[u][v];
 31             if(tmp==0){
 32                 T[v]=true;
 33                 if(!left[v]||match(left[v])){
 34                     left[v]=u;
 35                     return true;
 36                 }
 37             }else slack[v]=min(slack[v],tmp);
 38         }
 39     return false;
 40 }
 41 
 42 void update()
 43 {
 44     int a=INF;
 45     rep(v,1,n)
 46         if(!T[v])
 47             a=min(a,slack[v]);
 48     rep(i,1,n){
 49         if(S[i])Lx[i]-=a;
 50         if(T[i])Ly[i]+=a;
 51     }
 52 }
 53 
 54 void KM()
 55 {
 56     rep(i,1,n){
 57         left[i]=Ly[i]=0;
 58         Lx[i]=-INF;
 59         rep(j,1,n)
 60             Lx[i]=max(Lx[i],gap[i][j]);
 61     }
 62     rep(i,1,n){
 63         rep(j,1,n)
 64             slack[j]=INF;
 65         while(1)
 66         {
 67             rep(j,1,n)
 68                 S[j]=T[j]=0;
 69             if(match(i))
 70                 break;
 71             else
 72                 update();
 73         }
 74     }
 75 }
 76 
 77 void print()
 78 {
 79     int ans=0;
 80     rep(i,1,n){
 81         ans+=Lx[i];
 82         if(i!=1)printf(" ");
 83         printf("%d",Lx[i]);
 84 
 85     }
 86     printf("\n");
 87     rep(i,1,n){
 88         ans+=Ly[i];
 89         if(i!=1)printf(" ");
 90         printf("%d",Ly[i]);
 91     }
 92     printf("\n");
 93     printf("%d\n",ans);
 94 }
 95 
 96 int main()
 97 {
 98     while(~scanf("%d",&n))
 99     {
100         read();
101         KM();
102         print();
103     }
104     return 0;
105 }
View Code

 

posted @ 2013-09-01 12:31  Thousand Sunny  阅读(284)  评论(0编辑  收藏  举报