题意:一个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 }