zoukankan      html  css  js  c++  java
  • uva 1411(二分图最大权匹配)

    题意:平面坐标系中有一堆白点与黑点,告诉你他们的坐标,然后让你把他们连接起来,每个白点恰好连接一个黑点。线段不能相交。最后输出每个白点匹配的黑点的序号。

    思路:构造二分图每个白点对应一个x结点,黑点对应一个y结点权值是两者的欧氏距离相反数。之后最佳完全匹配就是解,原因是若存在(a,b)(c,d)两个匹配是相交的,那么必定存在(a,c)(b,d)比原来权值更大且不相交。

    代码如下:

      1 /**************************************************
      2  * Author     : xiaohao Z
      3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
      4  * Last modified : 2014-02-20 20:29
      5  * Filename     : uva_1411.cpp
      6  * Description     : 
      7  * ************************************************/
      8 
      9 #include <iostream>
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <cstdlib>
     13 #include <cmath>
     14 #include <algorithm>
     15 #include <queue>
     16 #include <stack>
     17 #include <vector>
     18 #include <set>
     19 #include <map>
     20 #define MP(a, b) make_pair(a, b)
     21 #define PB(a) push_back(a)
     22 #define PF(a) ((a)*(a))
     23 
     24 using namespace std;
     25 typedef long long ll;
     26 typedef pair<int, int> pii;
     27 typedef pair<unsigned int,unsigned int> puu;
     28 typedef pair<int, double> pid;
     29 typedef pair<ll, int> pli;
     30 typedef pair<int, ll> pil;
     31 
     32 const double INF = 1e30;
     33 const double eps = 1E-6;
     34 const int LEN = 1010;
     35 double g[LEN][LEN], lx[LEN], ly[LEN], slack[LEN];
     36 int linker[LEN], visx[LEN], visy[LEN], tlinker[LEN];
     37 int nx, ny;
     38 struct P {double x, y;};
     39 P white[LEN], black[LEN];
     40 
     41 double dis(P c, P d){return sqrt(PF(c.x - d.x) + PF(c.y - d.y));}
     42 
     43 bool DFS(int x)
     44 {
     45     visx[x] = 1;
     46     for(int y = 0; y < ny; y++)
     47     {
     48         if(visy[y])continue;
     49         double tmp = lx[x] + ly[y] - g[x][y];
     50         if(fabs(tmp) < eps)
     51         {
     52             visy[y] = 1;
     53             if(linker[y] == -1 || DFS(linker[y]))
     54             {
     55                 linker[y] = x;
     56                 tlinker[x] = y;
     57                 return true;
     58             }
     59         }
     60         else if(slack[y] > tmp)
     61             slack[y] = tmp;
     62     }
     63     return false;
     64 }
     65 double KM()
     66 {
     67     memset(linker,-1,sizeof(linker));
     68     memset(ly,0,sizeof(ly));
     69     for(int i = 0;i < nx;i++)
     70     {
     71         lx[i] = -INF;
     72         for(int j = 0;j < ny;j++)
     73             if(g[i][j] > lx[i])
     74                 lx[i] = g[i][j];
     75     }
     76     for(int x = 0;x < nx;x++)
     77     {
     78         for(int i = 0;i < ny;i++)
     79             slack[i] = INF;
     80         while(1)
     81         {
     82             memset(visx,0,sizeof(visx));
     83             memset(visy,0,sizeof(visy));
     84             if(DFS(x))break;
     85             double d = INF;
     86             for(int i = 0;i < ny;i++)
     87                 if(!visy[i] && d > slack[i])
     88                     d = slack[i];
     89             for(int i = 0;i < nx;i++)
     90                 if(visx[i])
     91                     lx[i] -= d;
     92             for(int i = 0;i < ny;i++)
     93             {
     94                 if(visy[i])ly[i] += d;
     95                 else slack[i] -= d;
     96             }
     97         }
     98     }
     99     double res = 0;
    100     for(int i = 0;i < ny;i++)
    101         if(linker[i] != -1)
    102             res += g[linker[i]][i];
    103     return res;
    104 }
    105 
    106 
    107 int main()
    108 {
    109 //    freopen("in.txt", "r", stdin);
    110 
    111     int n, kase = 1;
    112     while(scanf("%d", &n)!=EOF){
    113         if(kase != 1) printf("
    ");
    114         kase ++;
    115         nx = ny = n;
    116         for(int i=0; i<n; i++)
    117             scanf("%lf%lf", &white[i].x, &white[i].y);
    118         for(int i=0; i<n; i++)
    119             scanf("%lf%lf", &black[i].x, &black[i].y);
    120         for(int i=0; i<n; i++)
    121             for(int j=0; j<n; j++)
    122                 g[j][i] = -dis(white[i], black[j]);
    123         KM();
    124         for(int i=0; i<n; i++){
    125             printf("%d
    ", linker[i]+1);
    126         }
    127     }
    128     return 0;
    129 }
    View Code
    奔跑吧!少年!趁着你还年轻
  • 相关阅读:
    Prometheus—告警altermanger
    Prometheus监控Kafka
    get与post(转)
    js typeof
    设置SQL脚本大小敏感
    max Count Group by
    统计当年登陆次数
    IOC
    ORM
    [转载]C#实现获取浏览器信息
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3577150.html
Copyright © 2011-2022 走看看