1 条题解

  • 0
    @ 2026-1-31 0:06:06
    #include <iostream>
    #include <limits>
    #include <queue>
    #include <vector>
    using namespace std;
    
    template <typename T>
    struct hungarian {  // km
      int n;
      vector<int> matchx, matchy, pre;
      vector<bool> visx, visy;
      vector<T> lx, ly;
      vector<vector<T>> g;
      vector<T> slack;
      T inf, res;
      queue<int> q;
      int org_n, org_m;
    
      hungarian(int _n, int _m) {
        org_n = _n;
        org_m = _m;
        n = max(_n, _m);
        inf = numeric_limits<T>::max();
        res = 0;
        g = vector<vector<T>>(n, vector<T>(n));
        matchx = vector<int>(n, -1);
        matchy = vector<int>(n, -1);
        pre = vector<int>(n);
        visx = vector<bool>(n);
        visy = vector<bool>(n);
        lx = vector<T>(n, -inf);
        ly = vector<T>(n);
        slack = vector<T>(n);
      }
    
      void addEdge(int u, int v, int w) {
        g[u][v] = max(w, 0);  // 负值还不如不匹配 因此设为0不影响
      }
    
      bool check(int v) {
        visy[v] = true;
        if (matchy[v] != -1) {
          q.push(matchy[v]);
          visx[matchy[v]] = true;
          return false;
        }
        while (v != -1) {
          matchy[v] = pre[v];
          swap(v, matchx[pre[v]]);
        }
        return true;
      }
    
      void bfs(int i) {
        while (!q.empty()) {
          q.pop();
        }
        q.push(i);
        visx[i] = true;
        while (true) {
          while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int v = 0; v < n; v++) {
              if (!visy[v]) {
                T delta = lx[u] + ly[v] - g[u][v];
                if (slack[v] >= delta) {
                  pre[v] = u;
                  if (delta) {
                    slack[v] = delta;
                  } else if (check(v)) {
                    return;
                  }
                }
              }
            }
          }
          // 没有增广路 修改顶标
          T a = inf;
          for (int j = 0; j < n; j++) {
            if (!visy[j]) {
              a = min(a, slack[j]);
            }
          }
          for (int j = 0; j < n; j++) {
            if (visx[j]) {  // S
              lx[j] -= a;
            }
            if (visy[j]) {  // T
              ly[j] += a;
            } else {  // T'
              slack[j] -= a;
            }
          }
          for (int j = 0; j < n; j++) {
            if (!visy[j] && slack[j] == 0 && check(j)) {
              return;
            }
          }
        }
      }
    
      void solve() {
        // 初始顶标
        for (int i = 0; i < n; i++) {
          for (int j = 0; j < n; j++) {
            lx[i] = max(lx[i], g[i][j]);
          }
        }
    
        for (int i = 0; i < n; i++) {
          fill(slack.begin(), slack.end(), inf);
          fill(visx.begin(), visx.end(), false);
          fill(visy.begin(), visy.end(), false);
          bfs(i);
        }
    
        // custom
        for (int i = 0; i < n; i++) {
          if (g[i][matchx[i]] > 0) {
            res += g[i][matchx[i]];
          } else {
            matchx[i] = -1;
          }
        }
        cout << res << "\n";
        for (int i = 0; i < org_n; i++) {
          cout << matchx[i] + 1 << " ";
        }
        cout << "\n";
      }
    };
    
    int main() {
      ios::sync_with_stdio(false), cin.tie(nullptr);
      int n, m, e;
      cin >> n >> m >> e;
    
      hungarian<long long> solver(n, m);
    
      int u, v, w;
      for (int i = 0; i < e; i++) {
        cin >> u >> v >> w;
        u--, v--;
        solver.addEdge(u, v, w);
      }
      solver.solve();
    }
    
    • 1

    信息

    ID
    4793
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    6
    已通过
    1
    上传者