poj 3565 KM
要不是做这题之前就知道可以用km匹配做的话,估计也想不出最短距离和的匹配一定不会交叉。。。
画个图:假如A<->C B<->D匹配后的距离和值最小且交于E.则一定可以得到 A<->D B<->C的匹配的距离和小于A<->C B<->D。矛盾。故最小匹配后一定无交点。
Km算法求二分图最优值匹配:
注意要用:double。。。明明说了是Each ant colony and apple tree is described by a pair of integer coordinates x and y (−10 000 ≤ x, y ≤ 10 000) on a Cartesian plane.用longlong 也不行。。不知道为啥。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 7 using namespace std; 8 9 #define MAXN 110 10 #define MAXM 110 11 #define inf 9999999999.0 12 #define eps 1e-5 13 #define Abs(t) (t>0?t:-t) 14 double w[MAXN][MAXM]; 15 double lx[MAXN],ly[MAXM]; 16 int linky[MAXM]; 17 bool visx[MAXN],visy[MAXM]; 18 double slack[MAXM]; 19 int nx,ny; 20 21 struct point 22 { 23 double x,y;//double.. 24 }ant[MAXN],apple[MAXM]; 25 26 bool find(int x) 27 { 28 visx[x]=1; 29 for(int y=1;y<=ny;y++) 30 { 31 if(visy[y]) continue; 32 double t=lx[x]+ly[y]-w[x][y]; 33 if(Abs(t)<eps) 34 { 35 visy[y]=1; 36 if(linky[y] == -1 || find(linky[y])) 37 { 38 linky[y]=x; 39 return true; 40 } 41 } 42 else if(slack[y] >t) 43 slack[y]=t; 44 } 45 return false; 46 } 47 void KM() 48 { 49 int i,j; 50 memset(linky,-1,sizeof(linky)); 51 memset(ly,0,sizeof(ly)); 52 for(i=1;i<=nx;i++) 53 { 54 lx[i]=-inf; 55 for(j=1;j<=ny;j++) 56 if(w[i][j] >lx[i]) 57 lx[i]=w[i][j]; 58 } 59 for(int x=1;x<=nx;x++) 60 { 61 for(i=1;i<=ny;i++) 62 slack[i]=inf; 63 while(true) 64 { 65 memset(visx,0,sizeof(visx)); 66 memset(visy,0,sizeof(visy)); 67 if(find(x)) break; 68 double d=inf; 69 for(i=1;i<=ny;i++) 70 if(!visy[i] && d>slack[i]) 71 d=slack[i]; 72 for(i=1;i<=nx;i++) 73 if(visx[i]) 74 lx[i]-=d; 75 for(i=1;i<=ny;i++) 76 if(visy[i]) 77 ly[i]+=d; 78 else 79 slack[i]-=d; 80 } 81 } 82 } 83 84 double dist(point a,point b) 85 { 86 return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); 87 } 88 89 void init() 90 { 91 for(int i=1;i<=nx;i++) 92 scanf("%lf%lf",&ant[i].x,&ant[i].y); 93 for(int i=1;i<=ny;i++) 94 scanf("%lf%lf",&apple[i].x,&apple[i].y); 95 for(int i=1;i<=ny;i++) 96 for(int j=1;j<=nx;j++) 97 { 98 w[i][j]=-dist(apple[i],ant[j]); 99 } 100 } 101 102 void solve() 103 { 104 KM(); 105 for(int i=1;i<=ny;i++) 106 printf("%d\n",linky[i]); 107 108 } 109 110 int main() 111 { 112 while(scanf("%d",&nx) != EOF) 113 { 114 ny=nx; 115 init(); 116 solve(); 117 } 118 return 0; 119 }