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

     

  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/MingSD/p/9436476.html
Copyright © 2011-2022 走看看