1 solutions

  • -1
    @ 2025-11-28 19:35:52
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 100005;
    const int MAXM = 100005;
    const int LOG = 17;
    const ll INF = 1e18;
    
    struct Edge {
        int u, v, w, id;
        bool inMST;
    } edges[MAXM];
    
    bool cmpW(const Edge& a, const Edge& b) {
        return a.w < b.w;
    }
    
    bool cmpId(const Edge& a, const Edge& b) {
        return a.id < b.id;
    }
    
    int n, m;
    vector<pair<int, int>> g[MAXN]; // MST 树: to, weight, edge id?
    int parent[MAXN][LOG], depth[MAXN];
    ll best[MAXN][LOG]; // 最小替代边权值
    int uEdge[MAXN]; // 记录连接 u 和父节点的边的权值
    
    int dsu[MAXN];
    int find(int x) {
        return dsu[x] == x ? x : dsu[x] = find(dsu[x]);
    }
    
    void dfs(int u, int p, int w, int d) {
        parent[u][0] = p;
        uEdge[u] = w;
        depth[u] = d;
        for (int k = 1; k < LOG; k++) {
            parent[u][k] = parent[parent[u][k-1]][k-1];
            best[u][k] = INF;
        }
        best[u][0] = INF;
        for (auto& e : g[u]) {
            int v = e.first;
            if (v == p) continue;
            dfs(v, u, e.second, d+1);
        }
    }
    
    int lca(int u, int v) {
        if (depth[u] < depth[v]) swap(u, v);
        int diff = depth[u] - depth[v];
        for (int k = LOG-1; k >= 0; k--) {
            if (diff >> k & 1) {
                u = parent[u][k];
            }
        }
        if (u == v) return u;
        for (int k = LOG-1; k >= 0; k--) {
            if (parent[u][k] != parent[v][k]) {
                u = parent[u][k];
                v = parent[v][k];
            }
        }
        return parent[u][0];
    }
    
    void updatePath(int u, int anc, ll w) {
        int diff = depth[u] - depth[anc];
        for (int k = LOG-1; k >= 0; k--) {
            if (diff >> k & 1) {
                best[u][k] = min(best[u][k], w);
                u = parent[u][k];
            }
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        cin >> n >> m;
        for (int i = 0; i < m; i++) {
            cin >> edges[i].u >> edges[i].v >> edges[i].w;
            edges[i].id = i;
            edges[i].inMST = false;
        }
    
        // Kruskal
        sort(edges, edges + m, cmpW);
        for (int i = 1; i <= n; i++) dsu[i] = i;
        ll MSTsum = 0;
        for (int i = 0; i < m; i++) {
            int u = edges[i].u, v = edges[i].v, w = edges[i].w;
            int fu = find(u), fv = find(v);
            if (fu != fv) {
                dsu[fu] = fv;
                MSTsum += w;
                edges[i].inMST = true;
                g[u].push_back({v, w});
                g[v].push_back({u, w});
            }
        }
    
        // 建 MST 树
        dfs(1, 0, 0, 0);
    
        // 初始化 best
        for (int i = 1; i <= n; i++) {
            for (int k = 0; k < LOG; k++) {
                best[i][k] = INF;
            }
        }
    
        // 处理非树边
        for (int i = 0; i < m; i++) {
            if (!edges[i].inMST) {
                int u = edges[i].u, v = edges[i].v, w = edges[i].w;
                int a = lca(u, v);
                updatePath(u, a, w);
                updatePath(v, a, w);
            }
        }
    
        // 下放 best
        for (int k = LOG-1; k >= 1; k--) {
            for (int i = 1; i <= n; i++) {
                if (best[i][k] < INF) {
                    best[i][k-1] = min(best[i][k-1], best[i][k]);
                    int p = parent[i][k-1];
                    best[p][k-1] = min(best[p][k-1], best[i][k]);
                }
            }
        }
    
        // 恢复边原始顺序
        sort(edges, edges + m, cmpId);
    
        // 输出答案
        for (int i = 0; i < m; i++) {
            if (!edges[i].inMST) {
                cout << MSTsum << "\n";
            } else {
                int u = edges[i].u, v = edges[i].v;
                if (depth[u] < depth[v]) swap(u, v);
                // u 的父边就是这条边
                if (best[u][0] == INF) {
                    cout << "-1\n";
                } else {
                    cout << MSTsum - edges[i].w + best[u][0] << "\n";
                }
            }
        }
    
        return 0;
    }
    

    解析版,你值得拥有!

    Information

    ID
    2899
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    10
    Tags
    # Submissions
    4
    Accepted
    4
    Uploaded By