您的位置:首页 > 其它

poj2195 二分图带权最小匹配

2013-07-24 20:09 316 查看
详细介绍: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
,ly
;
int Stack
;
int next
;
bool visx
,visy
;
int n;
struct node
{
int x,y;
node(){}
node(int _x,int _y):x(_x),y(_y){}
};
vector<node>vec1,vec2;
vector<int>vec
;
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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: