zoukankan      html  css  js  c++  java
  • P4180 【模板】严格次小生成树[BJWC2010]

    其实这道题大概是一两周之前的考试题, 还是我之前做过的题.
    不过考试的时候50分和100分的做法都写跪了, 考试后也没有调出来.

    来填坑了.

    Bugs

    大概知道我考试时代码最大的bug是啥了.
    需要维护的是最大边和次大边, 但是我好像维护的是最小边和次小边.
    能得分才见鬼了

    昨天做的时候制造了很多bug, 捡其中最sb的几个来说一下

    • 上面讲了
    • 倍增维护了向上跳跳到那个位置和路径最大次大值, 我是先跳了之后再求的最大次大值.这样还有70分数据是真的水.
    • 去重里面加了个greater<int>()导致去重失败, 90分, 数据是真的水.

    优化

    把程序写对了之后, 发现开O2优化能过(而且很快), 不开就超时了, 原因大概是我用了太多的STL里面的东西, 如vector<int>, pair<int, int>, 众所周知, 因为STL使用模板元的缘故, 效率是相当的感动.
    于是替换成数组和简陋的手写小结构, 通过.

    然后又把合并两个最大值, 次大值的函数替换成运算符+=, +, 并且使用了switch避免了贼慢的分支结构.

    然后就卡到了599ms.

    真劲呢.

    然后就为了优化寻址, 把f(向上跳跳到那个位置)和g(路径最大次大值)合并成一个结构.
    反而变慢了一点. 也许是.....的原因吧.

    final code

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    const int N = 100005;
    const int M = 300005;
    const long long inf_ll = 1e15;
    const int MAXIN = 300000;
    char IN[MAXIN], *SS = IN, *TT = IN;
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    // #define gc() getchar()
    
    inline int read() {
        int now = 0; register char c = gc();
        for (; !isdigit(c); c = gc());
        for (; isdigit(c); now = now * 10 + c - '0', c = gc());
        return now;
    }
    using std:: min;
    using std:: max;
    struct Pair {
        int first, second, third;
        Pair() {}
        Pair(int _, int __) : first(_), second(__) { }
        Pair(int _, int __, int ___) : first(_), second(__), third(___) { }
        Pair operator + (const Pair& o) const {
            switch(first == o.first ? 0 : (first > o.first ? 1 : -1)) {
                case 1:
                return Pair(first, max(o.first, second), o.third); break;
                case -1:
                return Pair(o.first, max(first, o.second), o.third); break;
                default:
                return Pair(first, max(second, o.second), o.third);
            }
        }
        void operator += (const Pair& o) {
            switch(first == o.first ? 0 : (first > o.first ? 1 : -1)) {
                case 1:
                second = max(second, o.first); break;
                case -1:
                second = max(first, o.second); first = o.first; break;
                default:
                second = max(second, o.second);
            }
        }
    };
    class Graph {
        struct Edge {
            int v, c; Edge* nxt;
            Edge(int _, int __, Edge* ___) : v(_), c(__), nxt(___) {}
        } *head[N];
        int n;
        int dep[N];
        Pair g[N][17];
        void dfs(int u, int fa) {
            dep[u] = dep[fa] + 1;
            for (auto edge = head[u]; edge; edge = edge->nxt) {
                int v = edge->v; if (v == fa) continue;
                g[v][0] = Pair(edge->c, -1, u);
                dfs(v, u);
            }
        }
      public:
        Graph(int _) : n(_) {}
        void AddEdge(int _, int __, int ___) {
            head[_] = new Edge(__, ___, head[_]);
            head[__] = new Edge(_, ___, head[__]);
        }
        void init() {
            g[1][0] = Pair(-1, -1, 0);
            dfs(1, 0);
            for (int i = 1; i < 17; i += 1)
                for (int j = 1; j <= n; j += 1)
                    g[j][i] = g[j][i - 1] + g[g[j][i - 1].third][i - 1];
        }
        Pair lca(int u, int v) {
            if (dep[u] < dep[v]) std :: swap(u, v);
            if (v == g[u][0].third) return Pair(-1, -1);
            Pair res = Pair(-1, -1);
            for (int i = 16; ~i; i -= 1)
                if (dep[g[u][i].third] >= dep[v]) {
                    res += g[u][i], u = g[u][i].third;
                }
            for (int i = 16; ~i; i -= 1)
                if (g[u][i].third != g[v][i].third)
                    res += g[u][i] + g[v][i],
                    u = g[u][i].third, v = g[v][i].third;
            return u == v ? res : res + g[u][0] + g[v][0];
        }
    };
    class Solution {
      private:
        int n, m;
        int find(int u) { return u == f[u] ? u : f[u] = find(f[u]); }
        struct Edge {
            int u, v, c;
            bool operator < (const Edge& o) const {
                return c < o.c;
            }
            Edge() {}
            Edge(int p) : u(read()), v(read()), c(read()) { }
        };
        Graph* G;
        Edge edge[M];
        int f[N], vis[M];
        long long Val;
      public:
        Solution(int _, int __) : n(_), m(__) { }
        void init() {
            G = new Graph(n);
            for (int i = 0; i < m; i += 1)
                edge[i] = Edge(1);
            std:: sort(edge, edge + m);
            for (int i = 1; i <= n; i += 1) f[i] = i;
            int rd = 0; Val = 0;
            for (int i = 0; i < m and rd < n; i += 1) {
                Edge* e = &edge[i];
                int fu = find(e->u), fv = find(e->v);
                if (fu != fv)
                    f[fu] = fv, rd += 1, Val += 1ll * e->c,
                    G->AddEdge(e->u, e->v, e->c), vis[i] = true;
                else vis[i] = false;
            }
            G->init();
        }
        long long getans() {
            long long Res = inf_ll;
            for (int i = 0; i < m; i += 1)
                if (not vis[i]) {
                    auto e = &edge[i];
                    int u = e->u, v = e->v, c = e->c;
                    Pair p = G->lca(u, v);
                    if (p.first == c) {
                        if (~p.second) Res = std:: min(Res, Val + c - p.second);
                    } else Res = std:: min(Res, Val + c - p.first);
                }
            return Res;
        }
    };
    
    int main () {
        int n = read(), m = read();
        Solution* Sol = new Solution(n, m);
        Sol->init();
        std:: cout << Sol->getans();
        return 0;
    }
    
  • 相关阅读:
    .htaccess中的apache rewrite规则写法详解(未完)
    Linux LVM逻辑卷配置过程详解(创建、扩展、缩减、删除、卸载、快照创建)(未完)
    Linux的单用户模式
    linux proc目录和常用操作
    struts2 中的 addActionError 、addFieldError、addActionMessage的方法
    OGNL和类型转换
    ognl概念和原理详解
    java垃圾回收器
    java堆和栈的区别
    js的call()通俗解释
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/9834646.html
Copyright © 2011-2022 走看看