2016年8月20日 星期六

TIOJ 1042 老問題

TIOJ 1042 老問題

題目概述:
二分圖最大權完美匹配 裸題。
注意負數要改成0。

思路:
以下給出的做法為O(N^4),且無特別優化。
但個人認為這是比較直觀且比較好寫不會有bug的寫法。
有的時候太注重再一些優化,反而在競賽時會出一些bug。


//By SCJ
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define INF 10000000
int n,a[102][102],lx[102],ly[102],match[102];
bool vx[102],vy[102];

bool dfs(int x)
{
   vx[x]=1;
   for(int y=1;y<=n;++y)
   {
       if(vy[y]) continue;
       int d=lx[x]+ly[y]-a[x][y];
       if(d==0)
       {
           vy[y]=1;
           if(match[y]==-1||dfs(match[y]))
           {
               match[y]=x;
               return 1;
           }
       }
   }
   return 0;
}

int KM()
{
   memset(match,-1,sizeof(match));
   for(int i=1;i<=n;++i)
   {
       lx[i]=-INF;
       for(int j=1;j<=n;++j)
           lx[i]=max(lx[i],a[i][j]);
   }

   for(int x=1;x<=n;++x)
   {
       while(1)
       {
           memset(vx,0,sizeof(vx));
           memset(vy,0,sizeof(vy));
           if(dfs(x)) break;
           int d=INF;
           for(int i=1;i<=n;++i) if(vx[i])
               for(int j=1;j<=n;++j) if(!vy[j])
                   d=min(d,lx[i]+ly[j]-a[i][j]);
           for(int i=1;i<=n;++i)
           {
               if(vx[i]) lx[i]-=d;
               if(vy[i]) ly[i]+=d;
           }
       }
   }
   int ans=0;
   for(int i=1;i<=n;++i) ans+=lx[i]+ly[i];
   return ans;
}

int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
   while(cin>>n,n!=0)
   {
       for(int i=1;i<=n;++i)
           for(int j=1;j<=n;++j) cin>>a[i][j],a[i][j]=max(a[i][j],0);
       cout<<KM()<<endl;
   }
}






沒有留言:

張貼留言