HDU 6346 整数规划 二分图匹配最优解

整数规划

原来的km+hunger跑法T了, 拿了一个新的板子, 新的写法是将这原来的找新的最小的d放在了上一次的残留图上,从而减小复杂度, 但是个人还不是很理解为什么最小的d下一次出现的位置一定是这次出现的位置的对应的x的点。

复杂度:n^3

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 const int inf = 0x3f3f3f3f;
 5 const LL INF = 0x3f3f3f3f3f3f3f3f;
 6 const int N = 210;
 7 int val[N][N];
 8 LL lx[N],ly[N];
 9 int linky[N];
10 LL pre[N];
11 bool vis[N];
12 bool visx[N],visy[N];
13 LL slack[N];
14 int n;
15 void bfs(int k){
16     LL px, py = 0,yy = 0, d;
17     memset(pre, 0, sizeof(LL) * (n+2));
18     memset(slack, inf, sizeof(LL) * (n+2));
19     linky[py]=k;
20     do{
21         px = linky[py],d = INF, vis[py] = 1;
22         for(int i = 1; i <= n; i++)
23             if(!vis[i]){
24                 if(slack[i] > lx[px] + ly[i] - val[px][i])
25                     slack[i] = lx[px] + ly[i] -val[px][i], pre[i]=py;
26                 if(slack[i]<d) d=slack[i],yy=i;
27             }
28         for(int i = 0; i <= n; i++)
29             if(vis[i]) lx[linky[i]] -= d, ly[i] += d;
30             else slack[i] -= d;
31         py = yy;
32     }while(linky[py]);
33     while(py) linky[py] = linky[pre[py]] , py=pre[py];
34 }
35 void KM(){
36     memset(lx, 0, sizeof(int)*(n+2));
37     memset(ly, 0, sizeof(int)*(n+2));
38     memset(linky, 0, sizeof(int)*(n+2));
39     for(int i = 1; i <= n; i++)
40         memset(vis, 0, sizeof(bool)*(n+2)), bfs(i);
41 }
42 int main(){
43     int T;
44     scanf("%d", &T);
45     for(int _i = 1; _i <= T; _i++){
46         scanf("%d", &n);
47         for(int i = 1; i <= n; i++){
48             for(int j = 1; j <= n; j++){
49                 scanf("%d", &val[i][j]);
50                 val[i][j] = -val[i][j];
51             }
52         }
53         KM();
54         LL ans = 0;
55         for(int i = 1; i <= n; ++i)
56             ans += lx[i] + ly[i];
57         printf("Case #%d: %I64d
", _i, -ans);
58     }
59     return 0;
60 }
View Code

 

原文地址:https://www.cnblogs.com/MingSD/p/9436476.html