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\n", _i, -ans); 58 } 59 return 0; 60 }