P4180 严格次小生成树

搞得倍增,11K 自己将就着看吧。

#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 = 1e5 + 1;
const int maxm = 6e5 + 1;
const int maxd = 70;
const int inf = 1e15;

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

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 (register 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 (register int i = 1; i <= log2(dep[cur]) + 1; ++i) {
            fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
        }
        for (register 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 (register int i = 1; i <= log2(dep[u]) + 1; ++i) {
            int scond = sc[u][i - 1];
            int sconu = sc[fa[u][i - 1]][i - 1];
            int mnond = mn[u][i - 1];
            int mnonu = mn[fa[u][i - 1]][i - 1];
            if (mnond > mnonu) {
                sc[u][i] = max(mnonu, max(scond, sconu));
                mn[u][i] = mnond;
            } else if (mnond < mnonu) {
                sc[u][i] = max(mnond, max(scond, sconu));
                mn[u][i] = mnonu;
            } else {
                sc[u][i] = max(scond, sconu);
                mn[u][i] = mnonu;
            }
        }
        for (register 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 (register 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);
        for (register int i = 0; i < maxn; ++i) {
            for (register int j = 0; j < maxd; ++j) {
                mn[i][j] = sc[i][j] = -inf;
            }
        }
        get_mn_sc(1, 0);
    }

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

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

    int jump(int u, int k) {
        while (k) {
            u = fa[u][(int) (log2(k & -k))];
            k -= (k & -k);
        }
        return u;
    }

    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[jump(v, dep[v] - dep[lca_u_v] - (1 << 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[jump(u, dep[u] - dep[lca_u_v] - (1 << 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[jump(u, dep[u] - dep[lca_u_v] - (1 << lg2u))][lg2u]);
        int mv = max(mn[v][lg2v], mn[jump(v, dep[v] - dep[lca_u_v] - (1 << lg2v))][lg2v]);

        return max(mu, mv);
    }

    int get_sc_on_line(int u, int v) { // u is v's fafafafafafa...
        if (dep[u] > dep[v]) swap(u, v);
        int lg2 = (int) (log2(dep[v] - dep[u]));
        int scans;
        int mnu = mn[jump(v, dep[v] - dep[u] - (1 << lg2))][lg2];
        int mnv = mn[v][lg2];
        int scu = sc[jump(v, dep[v] - dep[u] - (1 << lg2))][lg2];
        int scv = sc[v][lg2];
        if (mnu != mnv) {
            scans = max(min(mnu, mnv), max(scu, scv));
        } else {
            scans = max(scu, scv);
        }
        return scans;
    }

    int get_sc(int u, int v) {
        if (u == v) return -inf;
        int lca_u_v = lca(u, v);
        if (lca_u_v == u || lca_u_v == v) {
            return get_sc_on_line(u, v);
        }
        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[jump(u, dep[u] - dep[lca_u_v] - (1 << lg2u))][lg2u]);
        int mnv = max(mn[v][lg2v], mn[jump(v, dep[v] - dep[lca_u_v] - (1 << lg2v))][lg2v]);
        int scu = get_sc_on_line(u, lca_u_v);
        int scv = get_sc_on_line(v, lca_u_v);

        if (mnu > mnv) {
            return max(mnv, max(scu, scv));
        } else if (mnu < mnv) {
            return max(mnu, max(scu, scv));
        } else {
            return max(scu, scv);
        }
    }
};

struct dsu {
    int fa[maxn];

    void init(int n) {
        for (register 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]};
        e[cnt].mir = (cnt % 2 == 1 ? cnt + 1 : cnt - 1);
        ee[cnt] = (edge) {u, v, w, head[v], (cnt % 2 == 1 ? cnt + 1 : cnt - 1), cnt};
        head[u] = cnt;
    }

    void init() {
        fin >> n >> m;
        for (register int i = 1; i <= m; ++i) {
            int u, v, w;
            fin >> u >> v >> w;
            if (u == v) {
                w = inf;
            }
            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;
        int qwq_qaq = 0;
        for (register int i = 1; i <= cnt; ++i) {
            int u = d.find(ee[i].from);
            int v = d.find(ee[i].to);
            if (u != v) {
                qwq_qaq++;
                ans += ee[i].weight;
                d.fa[u] = v;
                intree[ee[i].org] = true;
                intree[ee[i].mir] = true;
                // cout << ee[i].from << " " << ee[i].to << " " << ee[i].weight << endl;
                // cout << ee[i].org << " " << ee[i].mir << endl;
                tr.add_edge(ee[i].from, ee[i].to, ee[i].weight);
                tr.add_edge(ee[i].to, ee[i].from, ee[i].weight);
                if (qwq_qaq == n - 1) break;
            }
        }
        return ans;
    }

    int second_min_generate_tree() {
        int mn = inf;
        for (register int i = 1; i <= cnt; ++i) {
            if (intree[i]) continue;
            if (!(i & 1)) continue;
            int u = e[i].from;
            int v = e[i].to;
            int w = e[i].weight;
            // fout << u << " " << v << " " << w << endl;
            int mnuv = tr.get_mn(u, v);
            int scuv = tr.get_sc(u, v);
            // cout << mnuv << " " << scuv << endl;
            if (mnuv == -inf) {
                if (scuv == -inf) continue;
                if (w == mnuv) continue;
                mn = min(mn, w - mnuv);
            } else {
                if (w == mnuv) mn = min(mn, w - scuv);
                else mn = min(mn, w - mnuv);
            }
        }
        return (mn == inf ? -1 : mn);
    }
};

graph g;

signed main() {
    // freopen("ex_tree1.in", "r", stdin);
    g.init();
    // cout << endl;
    int rans = g.kruskal();
    // cout << rans << endl;
    tr.init();
    // tr.output();
    // while (true) {
    //     int u, v;
    //     cin >> u >> v;
    //     cout << tr.get_mn(u, v) << " " << tr.get_sc(u, v) << endl;
    // }
    // cout << tr.sc[6][1] << endl;
    // cout << tr.get_mn(2, 4) << endl;
    int mn = g.second_min_generate_tree();
    if (mn == -1) {
        fout << "No Solution!" << endl;
    } else {
        fout << rans + mn << endl;
    }

    return 0;
}

/*
5 6
1 4 16
2 4 8
2 5 6
2 3 5
3 4 1
3 5 3

*/
posted @   TernaKagiri  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示