zoukankan      html  css  js  c++  java
  • uva1411 最小值转最大值+二分图匹配

    这题给了n个白点和n个黑点坐标,计算出他们两两配对的总路程最少,

    我们算出他们之间的距离,为d,然后 w[j][i]=-d; 就将求最小值转化为求最大值,然后采用km进行匹配计算

     1 #include <algorithm>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <cmath>
     6 using namespace std;
     7 /* KM算法
     8 * 复杂度O(nx*nx*ny)
     9 * 求最大权匹配
    10 * 若求最小权匹配,可将权值取相反数,结果取相反数
    11 * 点的编号从0开始
    12 */
    13 const int N = 105;
    14 const double INF = 1000000.0;
    15 int nx,ny; //两边的点数
    16 double W[N][N]; //二分图描述
    17 int Left[N];//y中各点匹配状态
    18 double Lx[N],Ly[N]; // x,y中的点标号
    19 double slack[N];
    20 bool S[N],T[N];
    21 int fab(double a, double b){
    22    if(fabs(a-b)<0.00000000001) return 0;
    23    else return a-b>0?1:-1;
    24 }
    25 bool DFS(int x) {
    26     S[x] = true;
    27     for(int y = 0; y < ny; y++){
    28         if(T[y]) continue;
    29         double tmp = Lx[x] + Ly[y] - W[x][y];
    30         if(fab(tmp,0)==0){
    31             T[y] = true;
    32             if(Left[y] == -1 || DFS(Left[y])){
    33                 Left[y] = x;
    34                 return true;
    35             }
    36         }
    37         else if(slack[y] > tmp)
    38         slack[y] = tmp;
    39     }
    40     return false;
    41 }
    42 void KM(){
    43     memset(Left, -1, sizeof(Left));
    44     memset(Ly,0, sizeof(Ly));
    45     for(int i = 0;i < nx;i++){
    46     Lx[i] = -INF;
    47     for(int j = 0;j < ny;j++)
    48         if(W[i][j] > Lx[i])
    49             Lx[i] = W[i][j];
    50     }
    51     for(int x = 0;x < nx;x++){
    52         for(int i = 0;i < ny;i++)
    53             slack[i] = INF;
    54         while(true){
    55             memset(S, false, sizeof(S));
    56             memset(T, false, sizeof(T));
    57             if(DFS(x)) break;
    58             double d = INF;
    59             for(int i = 0;i < ny;i++)
    60             if(!T[i] && d > slack[i])
    61             d = slack[i];
    62             for(int i = 0;i < nx;i++)
    63                 if(S[i])
    64             Lx[i] -= d;
    65             for(int i = 0;i < ny;i++){
    66                 if(T[i])Ly[i] += d;
    67                 else slack[i] -= d;
    68             }
    69         }
    70     }
    71 }
    72 //HDU 2255
    73 double x1[N],x2[N],yy1[N],yy2[N];
    74 int main()
    75 {
    76     int n,cccc=0;
    77     while(scanf("%d",&n) == 1){
    78         if(cccc++)printf("
    ");
    79         for(int i = 0;i < n;i++)
    80            scanf("%lf%lf",&x1[i],&yy1[i]);
    81         for(int i=0; i<n; i++)
    82             scanf("%lf%lf",&x2[i],&yy2[i]);
    83         for(int i=0; i<n; i++)
    84             for(int j=0; j<n; j++)
    85               W[j][i]=-sqrt((x1[i]-x2[j])*(x1[i]-x2[j])+
    86                                     (yy1[i]-yy2[j])*(yy1[i]-yy2[j])
    87                            );
    88         nx = ny = n;
    89         KM();
    90         for(int i=0; i<n ;i++)
    91             printf("%d
    ",Left[i]+1);
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    V4L2 soccamera 子系统
    ubuntu10.04 vim 配置
    Video for Linux Two
    I2C总线的仲裁机制
    Android Camera 通过V4L2与kernel driver的完整交互过程
    ubuntu安装辞典
    v4l2 camera 驱动架构 之 isp controller 驱动
    Android Camera 运行流程
    CentOS 7.x安装图文示范
    同余与模运算
  • 原文地址:https://www.cnblogs.com/Opaser/p/4370297.html
Copyright © 2011-2022 走看看