8k, 10pts
查看原帖
8k, 10pts
362750
TernaryTree楼主2022/5/15 16:05
#include <bits/stdc++.h>
#define int long long
#define debug fout << "Debug: " << __LINE__ << endl;

using namespace std;

namespace FastIO
{
    struct instream
    {
        int base = 10;

        friend instream &operator>>(instream &in, int &num)
        {
            int flag = 1;
            int ans = 0;
            char ch = getchar();
            while (ch < '0' || ch > '9')
            {
                if (ch == '-')
                {
                    flag = -flag;
                }
                ch = getchar();
            }

            while (ch >= '0' && ch <= '9')
            {
                ans = ans * in.base + (ch - '0');
                ch = getchar();
            }
            num = ans * flag;
            return in;
        }
    };

    struct outstream
    {
        template<typename _CharT, typename _Traits = char_traits<_CharT>>
        struct typ {
            typedef basic_ostream<_CharT, _Traits>& (* end) (basic_ostream<_CharT, _Traits>&);
        };

        int base = 10;

        friend outstream &operator<<(outstream &out, int num)
        {
            if (num < 0)
            {
                putchar('-');
                num = -num;
            }
            if (num >= 10)
            {
                out << num / 10;
            }
            putchar(num % 10 + '0');
            return out;
        }

        friend outstream &operator<<(outstream &out, const char * s) {
            printf("%s", s);
            return out;
        }

        friend outstream &operator<<(outstream &out, string s) {
            cout << s;
            return out;
        }

        friend outstream &operator<<(outstream &out, typ<char>::end e) {
            puts("");
            return out;
        }
    };

    instream fin;
    outstream fout;
}

using namespace FastIO;

const int maxn = 2e5 + 1;
const int maxm = 7e5 + 1;
const int maxd = 50;

struct edge {
    int from, to, weight, next;
    int mir;
};

struct tree {
    int n, cnt;
    int head[maxn];
    edge e[maxm];
    int fa[maxn][maxd];
    int dep[maxn];

    int mn[maxn][maxd], sc[maxn][maxd];

    void get_dep(int u, int depth, int fat) {
        dep[u] = depth;
        for (int i = head[u]; i; i = e[i].next) {
            if (e[i].to != fat) {
                get_dep(e[i].to, depth + 1, u);
            }
        }
    } 

    void get_fa(int cur, int fat) {
        fa[cur][0] = fat;
        for (int i = 1; i <= log2(dep[cur]) + 1; i++) {
            fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
        }
        for (int i = head[cur]; i; i = e[i].next) {
            if (e[i].to != fat) {
                get_fa(e[i].to, cur);
            }
        }
    }

    void get_mn_sc(int u, int fat) {
        for (int i = 1; i <= log2(dep[u]) + 1; i++) {
            int mnond = mn[u][i - 1];
            int mnonu = mn[fa[u][i - 1]][i - 1];
            int scond = sc[u][i - 1];
            int sconu = sc[fa[u][i - 1]][i - 1];
            if (mnond > mnonu) {
                mn[u][i] = mnond;
                sc[u][i] = max(mnonu, scond);
            } else if (mnond < mnonu) {
                mn[u][i] = mnonu;
                sc[u][i] = max(mnond, sconu);
            } else {
                mn[u][i] = mnonu;
                sc[u][i] = max(scond, sconu);
            }
        }
        for (int i = head[u]; i; i = e[i].next) {
            if (e[i].to != fat) {
                mn[e[i].to][0] = e[i].weight;
                get_mn_sc(e[i].to, u);
            }
        }
    }

    int lca(int u, int v) {
        if (dep[u] < dep[v]) swap(u, v);
        while (dep[u] > dep[v]) {
            u = fa[u][(int) log2(dep[u] - dep[v])];
        }
        if (u == v) return u;
        for (int i = log2(dep[u]); i >= 0; i--) {
            if (fa[u][i] != fa[v][i]) {
                u = fa[u][i];
                v = fa[v][i];
            }
        }
        return fa[u][0];
    }


    void add_edge(int u, int v, int w) {
        e[++cnt] = (edge) {u, v, w, head[u]};
        head[u] = cnt;
    }

    void init() {
        get_dep(1, 0, 0);
        get_fa(1, 0);
        get_mn_sc(1, 0);
    }

    void output_e() {
        for (int i = 1; i <= cnt; i++) {
            fout << e[i].from << " " << e[i].to << " " << e[i].weight << endl;
        }
    }

    void output() {
        fout << n << endl;
        for (int i = 1; i <= n; i++) {
            fout << dep[i] << " ";
        }
        fout << endl;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= log2(dep[i]); j++) {
                fout << mn[i][j] << ' ';
            }
            fout << endl;
        }
        fout << endl;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= log2(dep[i]); j++) {
                fout << sc[i][j] << ' ';
            }
            fout << endl;
        }
    }

    int get_mn(int u, int v) {
        int lca_u_v = lca(u, v);
        if (lca_u_v == u) {
            int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
            int mnv = max(mn[v][lg2v], mn[lca_u_v - lg2v][lg2v]);
            return mnv;
        }
        if (lca_u_v == v) {
            int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
            int mnu = max(mn[u][lg2u], mn[lca_u_v - lg2u][lg2u]);
            return mnu;
        }
        int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
        int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
        int mu = max(mn[u][lg2u], mn[lca_u_v - lg2u][lg2u]);
        int mv = max(mn[v][lg2v], mn[lca_u_v - lg2v][lg2v]);
        
        return max(mu, mv);
    }

    int get_sc(int u, int v) {
        int lca_u_v = lca(u, v);
        if (lca_u_v == u) {
            int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
            int scv = max(sc[v][lg2v], sc[lca_u_v - lg2v][lg2v]);
            return scv;
        }
        if (lca_u_v == v) {
            int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
            int scu = max(sc[u][lg2u], sc[lca_u_v - lg2u][lg2u]);
            return scu;
        }
        int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
        int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
        int mnu = max(mn[u][lg2u], mn[lca_u_v - lg2u][lg2u]);
        int mnv = max(mn[v][lg2v], mn[lca_u_v - lg2v][lg2v]);

        int scu = max(sc[u][lg2u], sc[lca_u_v - lg2u][lg2u]);
        int scv = max(sc[v][lg2v], sc[lca_u_v - lg2v][lg2v]);
        if (mnu > mnv) {
            return max(mnv, scu);
        } else if (mnu < mnv) {
            return max(mnu, scv);
        } else {
            return max(scu, scv);
        }
    }
};

struct dsu {
    int fa[maxn];

    void init(int n) {
        for (int i = 1; i <= n; i++) {
            fa[i] = i;
        }
    }
    
    int find(int x) {
        if (fa[x] == x) {
            return x;
        }
        return fa[x] = find(fa[x]);
    }
};

tree tr;

struct graph {
    int n, m, cnt;
    int head[maxn];
    edge e[maxm];
    edge ee[maxm];
    bool intree[maxm];
    dsu d;

    void add_edge(int u, int v, int w) {
        e[++cnt] = (edge) {u, v, w, head[u], cnt ^ 1};
        ee[cnt] = (edge) {u, v, w, head[v], cnt ^ 1};
        head[u] = cnt;
    }

    void init() {
        fin >> n >> m;
        for (int i = 1; i <= m; i++) {
            int u, v, w;
            fin >> u >> v >> w;
            add_edge(u, v, w);
            add_edge(v, u, w);
        }
    }

    int kruskal() {
        sort(ee + 1, ee + cnt + 1, [](edge a, edge b) {
            return a.weight < b.weight;
        });
        int ans = 0;
        d = dsu();
        d.init(n);
        tr.n = n;
        for (int i = 1; i <= cnt; i++) {
            int u = d.find(ee[i].from);
            int v = d.find(ee[i].to);
            if (u != v) {
                ans += ee[i].weight;
                d.fa[u] = v;
                intree[i] = true;
                intree[e[i].mir] = true;
                tr.add_edge(ee[i].from, ee[i].to, ee[i].weight);
                tr.add_edge(ee[i].to, ee[i].from, ee[i].weight);
            }
        }
        return ans;
    }

    int second_min_generate_tree() {
        int mn = 2e9;
        for (int i = 1; i <= cnt; i++) {
            if (intree[i]) continue;
            int u = ee[i].from;
            int v = ee[i].to;
            int w = ee[i].weight;
            int mnuv = tr.get_mn(u, v);
            int scuv = tr.get_sc(u, v);
            if (w == mnuv) mn = min(mn, w - scuv);
            else mn = min(mn, w - mnuv);
        }
        return mn;
    }
};

graph g;

signed main() {
    g.init();
    int rans = g.kruskal();
    tr.init();
    int mn = g.second_min_generate_tree();
    fout << rans + mn << endl;
    return 0;
}
2022/5/15 16:05
加载中...