zoukankan      html  css  js  c++  java
  • 最小k度最小生成树模板

    代码是抄的

    题解是瞄的

    可我想学习的心是真的嘤嘤嘤

    然而

    还是上传一份ioi大神的论文吧

    链接:https://pan.baidu.com/s/1neIW9QeZEa0hXsUqJTjmeQ

    密码:blr4

    代码如下

    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <stack>
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <bitset>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #define fuck(x) cout<<"["<<x<<"]";
    #define FIN freopen("input.txt","r",stdin);
    #define FOUT freopen("output.txt","w+",stdout);
    //#pragma comment(linker, "/STACK:102400000,102400000")
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 25;
     
    using namespace std;
     
    struct Edge{
      int u, v, d;
      Edge() {}
      Edge(int a, int b, int c) : u(a), v(b), d(c) {}
      bool operator < (const Edge &e) const {
        return d < e.d;
      }
    };
     
    int n, m, k;
    int cnt;
    int ans;
    int f[maxn]; // 并查集
    map<string, int> nodes;
    vector<Edge> edges;
    Edge dp[maxn];
    int g[maxn][maxn];
    bool tree[maxn][maxn]; // tree[i][j]=true表示<i, j>这条边在最小生成树中
    int minEdge[maxn];
     
    int find(int p) {
      if (p == f[p]) return f[p];
      return f[p] = find(f[p]);
    }
     
    void unite(int p, int q) {
      f[find(p)] = find(q);
    }
     
    void kruskal() {
      sort(edges.begin(), edges.end());
      for (int i = 0; i < edges.size(); i++) {
        int p = edges[i].u;
        int q = edges[i].v;
        if (p == 1 || q == 1) continue; // 忽略根节点
        if (find(p) != find(q)) {
          unite(p, q);
          tree[p][q] = tree[q][p] = 1;
          ans += edges[i].d;
        }
      }
    }
     
    void dfs(int cur, int pre) {
      for (int i = 2; i <= cnt; i++) {
        if (i == pre || !tree[cur][i]) continue;
        if (dp[i].d == -1) {
          if (dp[cur].d > g[cur][i]) dp[i] = dp[cur];
          else {
            dp[i].u = cur;
            dp[i].v = i;
            dp[i].d = g[cur][i];
          }
        }
        dfs(i, cur);
      }
    }
     
    void solve() {
      int keyPoint[maxn];
      for (int i = 2; i <= cnt; i++) {
        if (g[1][i] != INF) {
          // 点i在哪颗最小生成树中
          int color = find(i);
          // 每颗最小生成树中距离根节点最近的点与根节点的距离
          if (minEdge[color] > g[1][i]) {
            minEdge[color] = g[1][i];
            keyPoint[color] = i;
          }
        }
      }
      for (int i = 1; i <= cnt; i++) {
        if (minEdge[i] != INF) {
          m++;
          tree[1][keyPoint[i]] = tree[keyPoint[i]][1] = 1;
          ans += g[1][keyPoint[i]];
        }
      }
      // 由i-1度生成树得i度生成树
      for (int i = m + 1; i <= k; i++) {
        memset(dp, -1, sizeof(dp));
        dp[1].d = -INF;
        for (int j = 2; j <= cnt; j++)
          if (tree[1][j]) dp[j].d = -INF;
        dfs(1, -1); // dp预处理
        int idx, minnum = INF;
        for (int j = 2; j <= cnt; j++) {
          if (minnum > g[1][j] - dp[j].d) {
            minnum = g[1][j] - dp[j].d;
            idx = j;
          }
        }
        if (minnum >= 0) break;
        tree[1][idx] = tree[idx][1] = 1;
        tree[dp[idx].u][dp[idx].v] = tree[dp[idx].v][dp[idx].u] = 0;
        ans += minnum;
      }
    }
     
    void init() {
      memset(g, 0x3f, sizeof(g));
      memset(tree, 0, sizeof(tree));
      memset(minEdge, 0x3f, sizeof(minEdge));
      m = 0;
      cnt = 1;
      ans = 0;
      nodes["Park"] = 1;
      for (int i = 0; i < maxn; i++)
        f[i] = i;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
      FIN
    #endif
      scanf("%d", &n);
      string s1, s2;
      int d;
      init();
      for (int i = 1; i <= n; i++) {
        cin >> s1 >> s2 >> d;
        if (!nodes[s1]) nodes[s1] = ++cnt;
        if (!nodes[s2]) nodes[s2] = ++cnt;
        int u = nodes[s1], v = nodes[s2];
        edges.push_back(Edge(u, v, d));
        g[u][v] = g[v][u] = min(g[u][v], d);
      }
      scanf("%d", &k);
      kruskal(); // 忽略根节点先计算一次最小生成树,此时得到一个森林
      solve();
      printf("Total miles driven: %d
    ", ans);
      return 0;
    }
    View Code
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    mysql应用技巧
    Python httplib学习
    桌标相关知识
    行业百科知识--Github
    Ghost win7 系统安装(虚拟机)
    记一次pycharm和vscode因网络问题插件下载失败的问题
    Pydiction补全插件
    MS17-010远程溢出漏洞(CVE-2017-0143)
    shell快速入门
    Yarn架构
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/9396625.html
Copyright © 2011-2022 走看看