树链剖分+线段树严格次小生成树77pts
查看原帖
树链剖分+线段树严格次小生成树77pts
800703
xxxxxxxb楼主2023/11/14 23:19

rt,ll开了,数组也往大了开了,#7WA#13RE

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = (int)5e5 + 7;
int read() {
    int res = 0, f = 1;
    char c = getchar();
    while(!isdigit(c)) {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(isdigit(c)) {
        res = (res << 1) + (res << 3) + c - '0';
        c = getchar();
    }
    return res * f;
}
int n, m, cnt, far[N], top[N], dfn[N], son[N], siz[N], rnk[N], dep[N], cdfn,
    wp[N], ans = LLONG_MAX, mstw;
bool vis[N];
struct E {
    int u, v, w;
} e[N];
void ins(int u, int v, int w) { e[++cnt] = {u, v, w}; }
vector<pair<int, int>> s[N];
struct dsu {
    int pa[N];
    void init() {
        for(int i = 1; i <= n; ++i) {
            pa[i] = i;
        }
    }
    int find(int x) { return x == pa[x] ? x : pa[x] = find(pa[x]); }
    void uni(int x, int y) {
        x = find(x), y = find(y);
        pa[x] = y;
    }
} d;
void dfs1(int cur, int fa) {
    siz[cur] = 1, dep[cur] = dep[fa] + 1, far[cur] = fa;
    for(auto [v, w] : s[cur]) {
        if(v == fa) continue;
        wp[v] = w;
        dfs1(v, cur);
        siz[cur] += siz[v];
        son[cur] = siz[son[cur]] < siz[v] ? v : son[cur];
    }
}
void dfs2(int cur, int tp) {
    top[cur] = tp;
    dfn[cur] = ++cdfn;
    rnk[cdfn] = cur;
    if(!son[cur]) return;
    dfs2(son[cur], tp);
    for(auto [v, _] : s[cur]) {
        if(v == far[cur] || v == son[cur]) continue;
        dfs2(v, v);
    }
}
struct Tree {
    int d1[N << 2], d2[N << 2];
    int ls(int p) { return p << 1; }
    int rs(int p) { return p << 1 | 1; }
    void pushup(int p) {
        vector<int> v = {d1[ls(p)], d2[ls(p)], d1[rs(p)], d2[rs(p)]};
        sort(v.begin(), v.end(), greater<int>());
        auto ed = unique(v.begin(), v.end());
        if(ed - v.begin() < 3)
            d1[p] = v[0], d2[p] = 0;
        else
            d1[p] = v[0], d2[p] = v[1];
    }
    void build(int s, int t, int p) {
        if(s == t) {
            d1[p] = wp[rnk[s]], d2[p] = 0;
            return;
        }
        int m = (s + t) >> 1;
        build(s, m, ls(p)), build(m + 1, t, rs(p));
        pushup(p);
    }
    vector<int> query(int l, int r, int s, int t, int p) {
        if(l <= s && t <= r) {
            return {d1[p], d2[p]};
        }
        int m = (s + t) >> 1;
        vector<int> res;
        if(l <= m) {
            auto tmp = query(l, r, s, m, ls(p));
            res.insert(res.end(), tmp.begin(), tmp.end());
        }
        if(r > m) {
            auto tmp = query(l, r, m + 1, t, rs(p));
            res.insert(res.end(), tmp.begin(), tmp.end());
        }
        sort(res.begin(), res.end(), greater<int>());
        auto ed = unique(res.begin(), res.end());
        if(ed - res.begin() < 2) return {res[0], 0};
        return {res[0], res[1]};
    }
} tree;
void krus() {
    int cnt1 = 0;
    sort(e + 1, e + 1 + m, [](const E &i, const E &j) { return i.w < j.w; });
    for(int i = 1; i <= m; ++i) {
        auto [u, v, w] = e[i];
        if(u == v) continue;
        if(d.find(u) == d.find(v)) continue;
        s[u].push_back({v, w}), s[v].push_back({u, w});
        d.uni(u, v);
        vis[i] = 1, mstw += w;
        if(++cnt1 == n - 1) break;
    }
}
void MST_2() {
    for(int i = 1; i <= m; ++i) {
        if(vis[i]) continue;
        auto [u, v, w] = e[i];
        if(u == v) continue;
        vector<int> res;
        while(top[u] != top[v]) {
            if(dep[u] < dep[v]) swap(u, v);
            auto tmp = tree.query(dfn[top[u]], dfn[u], 1, n, 1);
            res.insert(res.end(), tmp.begin(), tmp.end());
            sort(res.begin(), res.end(), greater<int>());
            auto ed = unique(res.begin(), res.end());
            if(ed - res.begin() == 1) {
                while(res.size() != 1) res.pop_back();
                res.push_back(0);
            } else {
                while(res.size() != 2) res.pop_back();
            }
            u = far[top[u]];
        }
        if(u != v) {
            if(dep[u] > dep[v]) swap(u, v);
            auto tmp = tree.query(dfn[u] + 1, dfn[v], 1, n, 1);
            res.insert(res.end(), tmp.begin(), tmp.end());
        }
        sort(res.begin(), res.end(), greater<int>());
        auto ed = unique(res.begin(), res.end());
        if(ed - res.begin() == 1) {
            while(res.size() != 1) res.pop_back();
            res.push_back(0);
        } else {
            while(res.size() != 2) res.pop_back();
        }
        assert(w >= res[0]);
        if(w == res[0]) {
            if(res[1])
            ans = min(ans, mstw - res[1] + w);
        } else {
            if(res[0])
            ans = min(ans, mstw - res[0] + w);
        }
    }
}
signed main() {
    n = read(), m = read();
    d.init();
    for(int i = 1; i <= m; ++i) {
        int u = read(), v = read(), w = read();
        ins(u, v, w);
    }
    krus();
    dfs1(1, 0);
    dfs2(1, 1);
    tree.build(1, n, 1);
    MST_2();
    return printf("%lld\n", ans), 0;
}
2023/11/14 23:19
加载中...