poj2195 二分图带权最小匹配

详细介绍:http://boj.5d6d.com/thread-1382-1-1.html

二分图的最小带权匹配为最大带权匹配的边取相反数,然后取得的最大匹配结果取相反数即可!

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
#include<map>
using namespace std;

#define rep(i,n) for(int i=0; i<(n); ++i)
#define repf(i,n,m) for(int i=(n); i<=(m); ++i)
#define repd(i,n,m) for(int i=(n); i>=(m); --i)
#define ll long long
#define inf 1000000000
#define exp 0.000000001
#define N 10010
int lx[N],ly[N];
int Stack[N];
int next[N];
bool visx[N],visy[N];
int n;
struct node
{
       int x,y;
       node(){}
       node(int _x,int _y):x(_x),y(_y){}
};
vector<node>vec1,vec2;
vector<int>vec[N];
int fab(int x) {if(x<0) return -x;return x;}

bool bfs(int u)
{
     visx[u]=true;
     rep(i,vec[u].size())
     {
//	 cout<<" sdfs"<<visy[i]<<endl;
        if(visy[i]==true) continue;
//		cout<<" "<<lx[u]<<" "<<ly[i]<<" "<<vec[u][i]<<endl;
        if(lx[u]+ly[i]==vec[u][i])
        {
          visy[i]=true;
          if(next[i]==-1 || bfs(next[i]))
          {
              next[i]=u; return true;
          }
        }
        else 
        Stack[i]=min(Stack[i],lx[u]+ly[i]-vec[u][i]);
     }
     return false;
}

int km()
{
    int sum=0;
    rep(i,n) lx[i]=-inf;
//	rep(i,n) cout<<lx[i]<<endl;
    rep(i,n)
    {
       ly[i]=0;
       rep(j,n) lx[i]=max(lx[i],vec[i][j]);
    }
//   rep(i,n) cout<<lx[i]<<endl;	
    memset(next,-1,sizeof(next));
    rep(i,n)
    {
	//	cout<<i<<endl;
        while(true)
        {
           memset(visx,false,sizeof(visx));
          rep(j,n) Stack[j]=inf; 
           memset(visy,false,sizeof(visy));
	//	   rep(j,n) cout<<"sdf"<<visy[j]<<endl;
           if(bfs(i))  break;
           int Max=inf;
           rep(j,n) if(visy[j]==false) Max=min(Max,Stack[j]);
	//	   cout<<" "<<Max<<endl;
           rep(j,n)
           {
              if(visx[j]==true) lx[j]-=Max;
              if(visy[j]==true) ly[j]+=Max;
           }
  //         rep(j,n) cout<<lx[j]<<" "<<ly[j]<<endl; getchar(); 
        }
    }
    int ans=0;
    rep(i,n)
    {
            ans+=vec[next[i]][i];
    }
    return -ans;
}
int main()
{
    int w,h;
    char s[N];
    while(scanf("%d%d",&w,&h))
    {
         if(w+h==0) break;
         vec1.clear(); vec2.clear();
         rep(i,w)
         {
             scanf("%s",s);
             rep(j,h)
             {
                 if(s[j]=='H') vec2.push_back(node(i,j));
                 if(s[j]=='m') vec1.push_back(node(i,j));
             }
         } 
         n=vec1.size();//人的个数的 
		 rep(i,n) vec[i].clear();
         rep(i,vec1.size())
           rep(j,vec2.size())
             vec[i].push_back(-(fab(vec1[i].x-vec2[j].x)+fab(vec1[i].y-vec2[j].y)));
       //  rep(i,n) rep(j,vec[i].size()) cout<<vec[i][j]<<endl;
		 printf("%d\n",km());     
//		cout<<"dfs"<<endl; 
    }
    return 0;
}


你可能感兴趣的:(poj2195 二分图带权最小匹配)