uva 11383(二分图最大权匹配)

题意:一个n*n的矩阵每个格子里有一个正整数w(i,j)你的任务是确定每行一个整数row(i)每列一个整数col(i),对每个格子都有w(i,j)<=row(i)+col(j)所有row(i)和col(i)和尽量小。

思路:本题利用KM算法l(x)+l(y)>=w(x,y)的性质直接可以知道得出的顶标之和即为最小的。

代码如下:

  1 /**************************************************
  2  * Author     : xiaohao Z
  3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
  4  * Last modified : 2014-03-02 14:04
  5  * Filename     : 11383.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 
 23 using namespace std;
 24 typedef long long ll;
 25 typedef pair<int, int> pii;
 26 typedef pair<unsigned int,unsigned int> puu;
 27 typedef pair<int, double> pid;
 28 typedef pair<ll, int> pli;
 29 typedef pair<int, ll> pil;
 30 
 31 const int INF = 0x3f3f3f3f;
 32 const double eps = 1E-6;
 33 const int LEN = 1010;
 34 int nx, ny, visx[LEN], visy[LEN], link[LEN];
 35 int Map[LEN][LEN], lx[LEN], ly[LEN], slack[LEN];
 36 
 37 bool dfs(int x){
 38     visx[x] = 1;
 39     for(int y=0; y<ny; y++)
 40     {
 41         if(visy[y]) continue;
 42         int tmp = lx[x] + ly[y] - Map[x][y];
 43         if(tmp == 0)
 44         {
 45             visy[y] = 1;
 46             if(link[y] == -1 || dfs(link[y]))
 47             {
 48                 link[y] = x;
 49                 return true;
 50             }
 51         }
 52         else if(slack[y] > tmp) 
 53             slack[y] = tmp;
 54     }
 55     return false;
 56 }
 57 
 58 int KM(){
 59     memset(link, -1, sizeof link);
 60     memset(ly, 0, sizeof ly);
 61     for(int i=0; i<nx; i++)
 62     {
 63         lx[i] = -INF;
 64         for(int j=0; j<ny; j++)
 65             if(Map[i][j] > lx[i])
 66                 lx[i] = Map[i][j];
 67     }
 68     for(int x=0; x<nx; x++)
 69     {
 70         for(int i=0; i<ny; i++)
 71             slack[i] = INF;
 72         while(1)
 73         {
 74             memset(visx, 0, sizeof visx);
 75             memset(visy, 0, sizeof visy);
 76             if(dfs(x)) break;
 77             int d = INF;
 78             for(int i=0; i<ny; i++)
 79                 if(!visy[i] && d > slack[i])
 80                     d = slack[i];
 81             for(int i=0; i<nx; i++)
 82                 if(visx[i]) 
 83                     lx[i] -= d;
 84             for(int i=0; i<ny; i++)
 85             {
 86                 if(visy[i]) ly[i] += d;
 87                 else slack[i] -= d;
 88             }
 89         }
 90     }
 91     int ret = 0;
 92     for(int i=0; i<ny; i++)
 93         if(link[i] != -1)
 94             ret += Map[link[i]][i];
 95     return ret;
 96 }
 97 
 98 int main()
 99 {
100 //    freopen("in.txt", "r", stdin);
101 
102     int n;
103     while(cin >> n){
104         nx = ny = n;
105         for(int i=0; i<n; i++)
106             for(int j=0; j<n; j++)
107                 cin >> Map[i][j];
108         KM();
109         for(int i=0; i<n; i++){
110             cout << lx[i];
111             if(i!=n-1)cout << ' ';
112         }    
113         cout << endl;
114         for(int i=0; i<n; i++) {
115             cout << ly[i];     
116             if(i!=n-1)cout << ' ';
117         }
118         cout << endl;
119         int ans = 0;
120         for(int i=0; i<n; i++) ans += (lx[i]+ly[i]);
121         cout << ans << endl;
122     }
123     return 0;
124 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3576824.html