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 ≤ xy ≤ 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 }

 

原文地址:https://www.cnblogs.com/Missa/p/2708604.html