费用流的模板题。
就是用KM跑一下最优匹配就好了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 310; 18 int val[N][N]; 19 int lx[N], ly[N], match[N]; 20 int visx[N], visy[N]; 21 int slack[N]; 22 int n; 23 void init(){ 24 memset(match, -1, sizeof(match)); 25 memset(ly, 0, sizeof(ly)); 26 memset(lx, -inf, sizeof(lx)); 27 } 28 bool hunger(int u){ 29 visx[u] = 1; 30 for(int i = 1; i <= n; i++){ 31 if(visy[i]) continue; 32 else { 33 if(lx[u] + ly[i] == val[u][i]){ 34 visy[i] = 1; 35 if(match[i] == -1 || hunger(match[i])){ 36 match[i] = u; 37 return true; 38 } 39 } 40 else slack[i] = min(slack[i], lx[u]+ly[i] - val[u][i]); 41 } 42 } 43 return false; 44 45 } 46 void KM_perferct_match(){ 47 for(int i = 1; i <= n; i++) 48 for(int j = 1; j <= n; j++) 49 lx[i] = max(lx[i], val[i][j]); 50 for(int i = 1; i <= n; i++){ 51 memset(slack, inf, sizeof(slack)); 52 while(1){ 53 memset(visx, 0, sizeof(visx)); 54 memset(visy, 0, sizeof(visy)); 55 if(hunger(i)) break; 56 else { 57 int tmp = inf; 58 for(int j = 1; j <= n; j++) 59 if(!visy[j]) tmp = min(tmp, slack[j]); 60 ///if(tmp == inf) break; 61 for(int j = 1; j <= n; j++){ 62 if(visx[j]) lx[j] -= tmp; 63 if(visy[j]) ly[j] += tmp; 64 else slack[j] -= tmp; 65 } 66 } 67 } 68 } 69 } 70 int main(){ 71 72 while(~scanf("%d", &n)){ 73 init(); 74 for(int i = 1; i <= n; i++) 75 for(int j = 1; j <= n; j++) 76 scanf("%d", &val[i][j]); 77 KM_perferct_match(); 78 int ans = 0; 79 for(int i = 1; i <= n; i++){ 80 if(match[i] != -1) ans += val[match[i]][i]; 81 } 82 printf("%d ", ans); 83 } 84 return 0; 85 }
注意的就是在这个跑法中,得到的结果是最大匹配的最大值是多少。
如果要求最小值的话,将值取反,变成负数,然后再套模板,跑出结果,最后再取反就是最小值了。