zoukankan      html  css  js  c++  java
  • uva11383 转化为 二分图匹配

    给定一个n*n矩阵,每个格子里都有一个正整数w(i,j)。你的任务是给每行确定一个整数row(i),没列也确定一个正整数col(i),使得对于任意格子(i,j),w(i,j) <= row(i)+col(j).所有row(i)和col(i)之和应最小

    由w(i,j)<=row(i)+col(j) 使用km算法时在推导的时候有这样一个公式 Lx[i]+Ly[i]>=W[i][j], 且KM使得 Lx[i]+Ly[i]==W[i][j],那么可以转化为KM来计算。

    每个row[i] 为Lx[i], 那么col[i]为Ly[i], w[i][j]为i和j连接的边的权重。

     1 #include <algorithm>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <vector>
     7 using namespace std;
     8 /* KM算法
     9 * 复杂度O(nx*nx*ny)
    10 * 求最大权匹配
    11 * 若求最小权匹配,可将权值取相反数,结果取相反数
    12 * 点的编号从0开始
    13 */
    14 const int N = 505;
    15 const int INF = 1000000;
    16 int nx,ny; //两边的点数
    17 int  W[N][N]; //二分图描述
    18 int Left[N],Lx[N],Ly[N]; //y中各点匹配状态 x,y中的点标号
    19 int slack[N];
    20 bool S[N],T[N];
    21 vector<int> G[N];
    22 bool DFS(int x) {
    23     S[x] = true;
    24     for(int y = 0; y < ny; y++){
    25         if(T[y]) continue;
    26         int tmp = Lx[x] + Ly[y] - W[x][y];
    27         if(tmp==0){
    28             T[y] = true;
    29             if(Left[y] == -1 || DFS(Left[y])){
    30                 Left[y] = x;
    31                 return true;
    32             }
    33         }
    34         else if(slack[y] > tmp)
    35         slack[y] = tmp;
    36     }
    37     return false;
    38 }
    39 void KM(){
    40     memset(Left, -1, sizeof(Left));
    41     memset(Ly,0, sizeof(Ly));
    42     for(int i = 0;i < nx;i++){
    43         Lx[i] = -INF;
    44         for(int j = 0;j < ny;j++)
    45              Lx[i] = max(Lx[i],W[i][j]);
    46     }
    47     for(int x = 0;x < nx;x++){
    48         for(int i = 0;i < ny;i++)
    49             slack[i] = INF;
    50         while(true){
    51             memset(S, false, sizeof(S));
    52             memset(T, false, sizeof(T));
    53             if(DFS(x)) break;
    54             int d = INF;
    55             for(int i = 0;i < ny;i++)
    56             if(!T[i] && d > slack[i])
    57             d = slack[i];
    58             for(int i = 0;i < nx;i++)
    59                 if(S[i])
    60             Lx[i] -= d;
    61             for(int i = 0;i < ny;i++){
    62                 if(T[i])Ly[i] += d;
    63                 else slack[i] -= d;
    64             }
    65         }
    66     }
    67 }
    68 //HDU 2255
    69 double x1[N],x2[N],yy1[N],yy2[N];
    70 int main()
    71 {
    72     int n;
    73     while(scanf("%d",&n) == 1){
    74         for(int i =0; i<n; i++){
    75              for(int j =0; j < n; ++j){
    76                  scanf("%d",&W[i][j]);
    77              }
    78         }
    79         nx = ny = n;
    80         KM();
    81         int sum=0;
    82         for(int i=0; i<n-1; i++) { printf("%d ",Lx[i]); sum+=Lx[i];} printf("%d
    ",Lx[n-1]);
    83         for(int i=0; i<n-1; i++) { printf("%d ",Ly[i]); sum+=Ly[i];}printf("%d
    ",Ly[n-1]);
    84         printf("%d
    ",sum+Lx[n-1]+Ly[n-1]);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    Cookie和Session
    HTTP简介
    Python赋值与深浅拷贝
    Python装饰器探险
    Python操作MongoDB数据库
    MongoDB数据库基础
    python操作mysql数据库
    USACO2012 overplanting /// 矩阵切割 递归 oj21547
    USACO2007 The Bale Tower /// DFS oj21160
    USACO2012 Moo /// 模拟 oj21548
  • 原文地址:https://www.cnblogs.com/Opaser/p/4370317.html
Copyright © 2011-2022 走看看