zoukankan      html  css  js  c++  java
  • hdu2121 Ice_cream's world II

    hdu2121 Ice_cream's world II

    给一个有向图,求最小树形图,并输出根节点

    (nleq10^3, mleq10^4)

    最小树形图


    对于求无根最小树形图,可以建一个虚拟节点,连向其他所有节点,权值为 (inf) ,最后的答案即为 (ans-inf) 。无解当且仅当 (ans>inf imes2)

    至于求根节点,可以考虑记下前驱为虚拟节点的节点,但由于节点编号不断改变,因此只需记下连接两个节点的边即可。

    时间复杂度 (O(nm))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1010, inf = 2e6;
    int n, m, tmp, val[maxn], tid[maxn], pre[maxn], vis[maxn];
    struct edges {
      int u, v, w;
    } e[maxn * 11];
    
    void edmonds() {
      int ans = 0, pos;
      while (1) {
        memset(tid, 0, sizeof tid);
        memset(vis, 0, sizeof vis);
        for (int i = 1; i < n; i++) {
          val[i] = 1 << 30;
        }
        for (int i = 1; i <= m; i++) {
          int u = e[i].u, v = e[i].v;
          if (u != v && e[i].w < val[v]) {
            val[v] = e[i].w, pre[v] = u;
            if (u == n) pos = i;
          }
        }
        for (int i = 1; i < n; i++) {
          if (val[i] > 1e9) {
            puts("impossible
    "); return;
          }
        }
        int tot = 0;
        for (int i = 1; i < n; i++) {
          int u = i;
          ans += val[i];
          while (u != n && !tid[u] && vis[u] != i) {
            vis[u] = i, u = pre[u];
          }
          if (u != n && !tid[u]) {
            tid[u] = ++tot;
            for (int v = pre[u]; u != v; v = pre[v]) {
              tid[v] = tot;
            }
          }
        }
        if (!tot) break;
        for (int i = 1; i <= n; i++) {
          if (!tid[i]) tid[i] = ++tot;
        }
        for (int i = 1; i <= m; i++) {
          int u = e[i].u, v = e[i].v;
          e[i].u = tid[u], e[i].v = tid[v];
          if (u != v) e[i].w -= val[v];
        }
        n = tot;
      }
      ans -= inf;
      if (ans > inf) {
        puts("impossible
    ");
      } else {
        printf("%d %d
    
    ", ans, pos - m + tmp - 1);
      }
    }
    
    int main() {
      while (~scanf("%d %d", &n, &m)) {
        for (int i = 1; i <= m; i++) {
          scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
          e[i].u++, e[i].v++;
        }
        for (int i = 1; i <= n; i++) {
          e[m + i].u = n + 1, e[m + i].v = i, e[m + i].w = inf;
        }
        m += (tmp = n), n++;
        edmonds();
      }
      return 0;
    }
    
  • 相关阅读:
    QuickContactBadge
    第一周——15选1
    UVA 10036 Divisibility
    POJ 3984 迷宫问题
    POJ 3258 River Hopscotch
    CodeForces 230A Dragons
    HDU 4450 Draw Something
    POJ 2485(PRIME算法)
    HDU 1213
    CodeForces 16E
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10388909.html
Copyright © 2011-2022 走看看