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; }
相关文章推荐
- 二分图完备匹配(最小费用 || KM) poj 2195 GoingHome
- 【POJ - 2195】Going Home(KM算法求二分图最小权匹配)
- POJ 2195 Going Home(KM算法——二分图最小权匹配)
- poj 2195 Going Home 二分图最小权匹配KM算法
- poj2195 Going Home(二分图的最小权匹配)
- POJ 2195 二分图最小权匹配KM算法
- poj 2195 Going Home--最小费用最大流--spfa--动态数组--或者用 最小权匹配
- poj 2195(KM求最小权匹配)
- poj 2195 - Going Home 二分图最优匹配 ek
- POJ 2195 Going Home【KM算法-二分图的最优匹配】
- POJ 3692Kindergarten(二分图最大匹配之最小顶点匹配)
- POJ 3041 Asteroid (二分匹配模板-二分图最小覆盖)
- POJ 2195 Going Home【二分图最优匹配.KM】
- POJ 3686 The Windy's (二分图最小权匹配 拆点 构图)
- poj 2594 二分图最大匹配最小路径覆盖
- POJ训练计划3041_Asteroids(二分图/最小点覆盖=最大匹配)
- POJ 2195 Going Home(二分图最大权值匹配) KM
- poj2195 Going Home 最小权值匹配
- POJ 2195 Going Home(最小权匹配、KM算法)
- poj 2195 Going Home(二分图最优匹配KM算法)