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 }

 

 

你可能感兴趣的:(poj)