二分图的最大权匹配(最小权匹配)KM算法
2014-08-10 00:03
387 查看
如果二分图的每条边都有的一个权值,如何求出权值和最大(最小)的匹配;
最小权值匹配可以转化最大权值匹配,只需将权值取相反数即可;
poj3565二分图最小权值匹配模板题目;
最小权值匹配可以转化最大权值匹配,只需将权值取相反数即可;
poj3565二分图最小权值匹配模板题目;
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<climits> #include<cctype> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<stack> #include<string> #define INF 1e15 #define eps 1e-6 #define MAX 1000 #define ll long long using namespace std; double w[MAX][MAX],Lx[MAX],Ly[MAX]; int Left[MAX],n; bool S[MAX],T[MAX]; bool match(int i){ S[i] = true; for (int j = 1; j<=n; j++) if (fabs(Lx[i] + Ly[j] - w[i][j]) <= eps && !T[j]){ T[j] = true; if (!Left[j] || match(Left[j])){ Left[j] = i; return true; } } return false; } void update(){ double a = INF; for (int i = 1; i<=n; i++) if (S[i]) for (int j = 1; j<=n; j++) if (!T[j]) a = min(a,Lx[i]+Ly[j] - w[i][j]); for (int i = 1; i<=n; i++){ if (S[i]) Lx[i] -= a; if (T[i]) Ly[i] += a; } } void KM(){ for (int i = 1; i<=n; i++){ Left[i] = 0; Ly[i] = 0; Lx[i] = -INF; //如果w[i][j]全是正整数的话可以将Lx[]赋0 for (int j = 1; j<=n; j++) Lx[i] = max(Lx[i],w[i][j]); } for (int i = 1; i<=n; i++){ while (1){ for (int j = 1; j<=n; j++) S[j] = T[j] = 0; if (match(i)) break; else update(); } } } struct Node{ int x, y; }p[MAX],q[MAX]; double dist(int i, int j){ return sqrt((double)(p[i].x - q[j].x)*(p[i].x - q[j].x) + (p[i].y - q[j].y) * (p[i].y - q[j].y)); } int ans[MAX]; int main(){ while (scanf("%d",&n) != EOF){ for (int i = 1; i<=n; i++) scanf("%d%d",&p[i].x,&p[i].y); for (int i = 1; i<=n; i++) scanf("%d%d",&q[i].x,&q[i].y); for (int i = 1; i<=n; i++) for (int j =1; j<=n; j++) w[i][j] = -dist(i,j); //将权值取反,转化为最大权值匹配 KM(); for (int i = 1; i<=n; i++) ans[Left[i]] = i; for (int i = 1; i<=n; i++) printf("%d\n",ans[i]); } return 0; }poj2195最小权值匹配;
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<climits> #include<cctype> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<stack> #include<string> #define INF 1000000000 #define eps 1e-6 #define MAX 1000 #define ll long long using namespace std; int w[MAX][MAX],Lx[MAX],Ly[MAX]; int Left[MAX],n; bool S[MAX],T[MAX]; bool match(int i){ S[i] = true; for (int j = 1; j<=n; j++) if (Lx[i] + Ly[j] == w[i][j] && !T[j]){ T[j] = true; if (!Left[j] || match(Left[j])){ Left[j] = i; return true; } } return false; } void update(){ int a = INF; for (int i = 1; i<=n; i++) if (S[i]) for (int j = 1; j<=n; j++) if (!T[j]) a = min(a,Lx[i]+Ly[j] - w[i][j]); for (int i = 1; i<=n; i++){ if (S[i]) Lx[i] -= a; if (T[i]) Ly[i] += a; } } void KM(){ for (int i = 1; i<=n; i++){ Left[i] = 0; Ly[i] = 0; Lx[i] = -INF; for (int j = 1; j<=n; j++) Lx[i] = max(Lx[i],w[i][j]); } for (int i = 1; i<=n; i++){ while (1){ for (int j = 1; j<=n; j++) S[j] = T[j] = 0; if (match(i)) break; else update(); } } } struct Node{ int x, y; }p[MAX],q[MAX]; int dist(int i, int j){ return abs(p[i].x - q[j].x) + abs(p[i].y - q[j].y); } char s[MAX][MAX]; int main(){ int u,v; while (scanf("%d%d",&u,&v) && !(u == 0 && v == 0)){ n = 0; int m = 0; for (int i=0; i<u; i++){ scanf("%s",s[i]); for (int j = 0; j<v; j++){ if (s[i][j] == 'm')p[++n] = (Node){i,j}; if (s[i][j] == 'H')q[++m] = (Node){i,j}; } } for (int i = 1; i<=n; i++) for (int j =1; j<=n; j++) w[i][j] = -dist(i,j); //取相反数,转化为最大权问题 KM(); int ans = 0; for (int i = 1; i<=n; i++) ans += dist(Left[i],i); printf("%d\n",ans); } return 0; }
相关文章推荐
- 二分图-最大匹配,最小路径覆盖,最小点覆盖(KM算法)
- POJ 1325Machine Schedule(二分图最大匹配最小点覆盖)
- KM算法详解+模板(二分图最大权值匹配)
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- POJ3692——Kindergarten (二分图求最小顶点覆盖 (即最大匹配))
- POJ3041 二分图(性质)最小点覆盖等于最大匹配数(匈牙利模板题)
- HDOJ---1151 Air Raid[匈牙利算法:最小路径覆盖数=原图顶点数–二分图最大匹配数]
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配(转)
- poj 1422 Air Raid(最小路径覆盖 + 二分图最大匹配)
- uoj #80. 二分图最大权匹配 KM算法
- 二分图的最大匹配匈牙利算法和最小支配集
- POJ 3041 Asteroids【二分图最大匹配.最小点覆盖】
- 二分图最大权匹配 KM算法 板子
- DAG的最小路径覆盖和二分图的最大匹配
- [题解] [网络流二十四题(三)] 最小路径覆盖问题(二分图最大匹配)
- 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配
- KM算法(二分图最大权匹配)
- POJ 2195 Going Home(KM算法——二分图最小权匹配)
- hdu 1150 二分图 最小点覆盖=最大匹配
- HDU2255 奔小康赚大钱 —— KM算法(二分图最大权匹配)