zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    camke 参数
    17.计算1-100之和+1-50的平方和+1-10的倒数
    16.求Sn=a+aa+aaa+aaaa.......之值
    15.计算1!+2!+3!+.....20!=?
    14.输出所有的“水仙花”
    13.企业发放的奖金根据利润提成
    12.输入一个成绩计算其A,B,C,D,E等级
    11.键盘输入小于1000的整数
    10.求方程的根
    2019考研历程回顾
  • 原文地址:https://www.cnblogs.com/MingSD/p/9436476.html
Copyright © 2011-2022 走看看