zoukankan      html  css  js  c++  java
  • 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 }

     

  • 相关阅读:
    android 中webview的屏幕适配问题
    Mongo Delete-19
    Android开发初体验
    Mybatis: 插件及分页
    紧急寻人:十三岁男孩昨日出走至今未回,大家帮忙扩散寻找!
    iOS 9,为前端世界都带来了些什么?「译」
    修改 Cucumber HTML 报告
    Android多模块混淆的问题
    吴裕雄--天生自然 诗经:村居
    吴裕雄--天生自然 诗经:太虚幻境
  • 原文地址:https://www.cnblogs.com/Missa/p/2708604.html
Copyright © 2011-2022 走看看