次小生成树

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxe = 1e4+50;


struct Edge {
    int lst;
    int to;
    int w;
}edge[maxe * 2];
int head[128];
int qsz;

inline void add(int u, int v, int w) {
    edge[qsz].lst = head[u];
    edge[qsz].to  = v;
    edge[qsz].w   = w;
    head[u] = qsz++;
}

struct Edge1 {
    int to;
    int st;
    int w;
    bool operator < (const Edge1 &a) const {
        return w < a.w;
    }
}edge1[maxe * 2];

int fa[128];
inline int find(int idx) { return fa[idx]==idx ? idx : fa[idx]=find(fa[idx]); }
bool sel[maxe*2];

int pa[128];
int deep[128];
int up[128][9];
int maxi[128][9];

void dfs(int u, int fa) {
//    printf("%d %d 
", u, fa);
    int i, v;
    pa[u] = fa;
    up[u][0] = fa;
    deep[u] = deep[fa] + 1;
    for (i=head[u]; i; i=edge[i].lst) {
        v = edge[i].to;
        if (v == fa) continue;
        maxi[v][0] = edge[i].w;
        dfs(v, u);
    }
}

void update(int n) {
    int i, j;
    for (i=1; i<9; ++i) {
        for (j=1; j<=n; ++j) {
            up[j][i] = up[up[j][i-1]][i-1];
            maxi[j][i] = max(maxi[j][i-1], maxi[up[j][i-1]][i-1]);
        }
    }
} 

inline int lca(int u, int v) {
    int i;
    if (deep[u] < deep[v]) swap(u, v);
    for (i=8; i>=0; --i) 
        if (deep[up[u][i]] >= deep[v]) u = up[u][i];
    if (v == u) return u;
    for (i=8; i>=0; --i) 
        if (up[u][i] != up[v][i]) {
            u = up[u][i];
            v = up[v][i];
        }
    return up[u][0];
}

inline int qmax(int u, int lc) {
    int i, res = 0;
    for (i=8; i>=0; --i) {
        if (deep[up[u][i]] >= deep[lc]) {
            res = max(res, maxi[u][i]);
            u = up[u][i];
        }
    }
    return res;
}

int main()
{
//    freopen("E:\input.txt", "r", stdin);
    
    int t, i, j, n, m, u, v, size, tx, ty, seg;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        
        qsz = 1;
        memset(head, 0, sizeof(head));
        memset(sel , 0, sizeof(sel ));
        memset(maxi, 0, sizeof(maxi));
        for (i=1; i<=n; ++i) fa[i] = i;
        
        for (i=1; i<=m; ++i) scanf("%d%d%d", &edge1[i].st, &edge1[i].to, &edge1[i].w);
        sort(edge1+1, edge1+m+1);
        size = 0;
        seg  = 0;
        for (i=1; i<=m; ++i) {
            u = edge1[i].st; v = edge1[i].to;
            tx = find(u); ty = find(v);
            if (tx == ty) continue;
            if (u == tx) size++;
            if (v == ty) size++;
            fa[tx] = ty;
            sel[i] = true;
            add(u, v, edge1[i].w); add(v, u, edge1[i].w);
            seg += edge1[i].w;
        }
        
        deep[0] = 0;
        dfs(1, 0);
        update(n);
        
        bool flag = true;
        int res = 0;
        int tmp = seg;
        for (i=1; i<=m; ++i) {
            if (!sel[i]) {
                if (flag) {
                    tmp = tmp + edge1[i].w;
                    flag = false;
                }
                u = edge1[i].st; v = edge1[i].to;
                int lc = lca(u, v);
                int t1 = max(qmax(u, lc), qmax(v, lc));
                tmp = min(tmp, seg-t1+edge1[i].w);
            }
        }
        printf("%d %d
", seg, tmp);
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/cgjh/p/9774101.html