uva1411 最小值转最大值+二分图匹配

这题给了n个白点和n个黑点坐标,计算出他们两两配对的总路程最少,

我们算出他们之间的距离,为d,然后 w[j][i]=-d; 就将求最小值转化为求最大值,然后采用km进行匹配计算

 1 #include <algorithm>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <cstdio>
 5 #include <cmath>
 6 using namespace std;
 7 /* KM算法
 8 * 复杂度O(nx*nx*ny)
 9 * 求最大权匹配
10 * 若求最小权匹配,可将权值取相反数,结果取相反数
11 * 点的编号从0开始
12 */
13 const int N = 105;
14 const double INF = 1000000.0;
15 int nx,ny; //两边的点数
16 double W[N][N]; //二分图描述
17 int Left[N];//y中各点匹配状态
18 double Lx[N],Ly[N]; // x,y中的点标号
19 double slack[N];
20 bool S[N],T[N];
21 int fab(double a, double b){
22    if(fabs(a-b)<0.00000000001) return 0;
23    else return a-b>0?1:-1;
24 }
25 bool DFS(int x) {
26     S[x] = true;
27     for(int y = 0; y < ny; y++){
28         if(T[y]) continue;
29         double tmp = Lx[x] + Ly[y] - W[x][y];
30         if(fab(tmp,0)==0){
31             T[y] = true;
32             if(Left[y] == -1 || DFS(Left[y])){
33                 Left[y] = x;
34                 return true;
35             }
36         }
37         else if(slack[y] > tmp)
38         slack[y] = tmp;
39     }
40     return false;
41 }
42 void KM(){
43     memset(Left, -1, sizeof(Left));
44     memset(Ly,0, sizeof(Ly));
45     for(int i = 0;i < nx;i++){
46     Lx[i] = -INF;
47     for(int j = 0;j < ny;j++)
48         if(W[i][j] > Lx[i])
49             Lx[i] = W[i][j];
50     }
51     for(int x = 0;x < nx;x++){
52         for(int i = 0;i < ny;i++)
53             slack[i] = INF;
54         while(true){
55             memset(S, false, sizeof(S));
56             memset(T, false, sizeof(T));
57             if(DFS(x)) break;
58             double d = INF;
59             for(int i = 0;i < ny;i++)
60             if(!T[i] && d > slack[i])
61             d = slack[i];
62             for(int i = 0;i < nx;i++)
63                 if(S[i])
64             Lx[i] -= d;
65             for(int i = 0;i < ny;i++){
66                 if(T[i])Ly[i] += d;
67                 else slack[i] -= d;
68             }
69         }
70     }
71 }
72 //HDU 2255
73 double x1[N],x2[N],yy1[N],yy2[N];
74 int main()
75 {
76     int n,cccc=0;
77     while(scanf("%d",&n) == 1){
78         if(cccc++)printf("\n");
79         for(int i = 0;i < n;i++)
80            scanf("%lf%lf",&x1[i],&yy1[i]);
81         for(int i=0; i<n; i++)
82             scanf("%lf%lf",&x2[i],&yy2[i]);
83         for(int i=0; i<n; i++)
84             for(int j=0; j<n; j++)
85               W[j][i]=-sqrt((x1[i]-x2[j])*(x1[i]-x2[j])+
86                                     (yy1[i]-yy2[j])*(yy1[i]-yy2[j])
87                            );
88         nx = ny = n;
89         KM();
90         for(int i=0; i<n ;i++)
91             printf("%d\n",Left[i]+1);
92     }
93     return 0;
94 }

 

posted @ 2015-03-26 22:27  来自大山深处的菜鸟  阅读(182)  评论(0编辑  收藏  举报