zoukankan      html  css  js  c++  java
  • 2020-08-16 省选集训选讲

    Problem T3. 高中题

    由于好路只会减少权值 (delta_a),坏路会增加权值 (delta_b)
    考虑这样一个不等式

    [w_a-delta _aleq w_b+delta _b ]

    移项可得

    [w_a-w_bleq delta_a+delta_b ]

    左边为边权,右边为顶标和。

    用 KM 计算出顶标。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 400;
    
    int g[N][N];
    
    int main() {
      int n, m;
      cin >> n >> m; 
      vector<int> weight(m);
      vector<vector<pair<int, int>>> graph(n); 
      for (int i = 0; i < n - 1; ++i) {
        int u, v, w; 
        cin >> u >> v >> w; 
        --u, --v; 
        weight[i] = w; 
        graph[u].emplace_back(v, i);
        graph[v].emplace_back(u, i);  
      }
      for (int i = n - 1; i < m; ++i) {
        int u, v, w; 
        cin >> u >> v >> w; 
        --u, --v; 
        weight[i] = w; 
        vector<int> vis(n, 0); 
        function<bool(int u, int goal)> dfs = [&](int u, int goal) {
          vis[u] = 1; 
          if (u == goal) {
            return true; 
          }
          for (auto e : graph[u]) {
            int v = e.first, id = e.second;
            if (vis[v]) {
              continue;
            }
            if (dfs(v, goal)) {
              if (weight[id] > w) {
                g[id][i - n + 1] = weight[id] - w; 
              }
              return true; 
            }
          }
          return false; 
        };
        dfs(u, v); 
      }
      auto km = [&]() {
        int N = max(n - 1, m - n + 1); 
        vector<bool> visx(N);
        vector<bool> visy(N); 
        vector<int> match(N); 
        vector<int> slack(N); 
        vector<int> valx(N); 
        vector<int> valy(N); 
        fill(match.begin(), match.end(), -1);
        for (int i = 0; i < N; ++i) {
          valx[i] = valy[i] = 0; 
          for (int j = 0; j < N; ++j) {
            valx[i] = max(valx[i], g[i][j]); 
          }
        }
        for (int i = 0; i < N; ++i) {
          fill(slack.begin(), slack.end(), 0x3f3f3f3f);
          while (true) {
            fill(visx.begin(), visx.end(), 0);
            fill(visy.begin(), visy.end(), 0); 
            function<bool(int u)> dfs = [&](int u) {
              visx[u] = 1; 
              for (int v = 0; v < N; ++v) {
                int w = g[u][v];  
                if (visy[v]) {
                  continue; 
                }
                if (valx[u] + valy[v] - w == 0) {
                  visy[v] = true; 
                  if (match[v] == -1 || dfs(match[v])) {
                    match[v] = u; 
                    return true; 
                  } 
                } else {
                  slack[v] = min(slack[v], valx[u] + valy[v] - w); 
                }
              }
              return false; 
            };
            if (dfs(i)) {
              break; 
            }
            int d = 0x3f3f3f3f;
            for (int j = 0; j < N; ++j) {
              if (!visy[j]) {
                d = min(d, slack[j]); 
              }
            }
            for (int j = 0; j < N; ++j) {
              if (visx[j]) {
                valx[j] -= d; 
              }
              if (visy[j]) {
                valy[j] += d; 
              } else {
                slack[j] -= d; 
              }
            }
          } 
        } 
        int ans = 0; 
        for (int i = 0; i < m; ++i) {
          ans += (i < n - 1 ? valx[i] : valy[i - n + 1]); 
        }
        cout << ans << '
    ';
      };
      km(); 
      return 0; 
    }
    
  • 相关阅读:
    WinCE数据库开发时整出来的一个致命的BUG
    WinCE下读取注册表获得SD卡路径
    Cookie的创建、读写和删除
    Http Module 介绍[转]
    贴几个从Dnt论坛代码里边扣出来的函数
    SqlServer判断数据库、表、存储过程、函数是否存在
    WinCE中C#WinForm利用Web Service查询数据库
    关于WinCE和PC中同一字符串的GetHashCode()结果不同的理解
    DataTable中数据记录的统计
    C#读取XML时自动过滤掉注释部分
  • 原文地址:https://www.cnblogs.com/chhokmah/p/13512856.html
Copyright © 2011-2022 走看看