• P4180 [BJWC2010]严格次小生成树


    P4180 BJWC2010严格次小生成树

    先求一遍最小生成树。然后枚举加入哪条边,然后找这两个端点的LCA,记录路径上的最大值和严格次大值(我用了一种偷懒的方法,不过能过)。为什么记录严格次大值?因为我们需要注意最大值等于你加入的边的情况。

    /*
    Name: P4180
    Copyright: NO
    Author: Gensokyo_Alice
    Date: 25/9/20 17:46
    Description:
    */
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <set>
    #include <map>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    
    struct edge {
        ll nt, to, v;
    } E[MAXN];
    
    struct edg {
        ll x, y, v;
        friend bool operator < (edg a, edg b) {
            return a.v < b.v;
        }
    } e[MAXN];
    
    struct zt {
        ll m1, m2, n;
    };
    
    ll q[4], tq, N, M, vis[MAXN], fa[MAXN], W, head[MAXN], cnt = -1, siz[MAXN], dep[MAXN], f[MAXN][22], dis[MAXN][2][22];
    
    zt lca(ll, ll);
    void add(ll, ll, ll);
    void dfs(ll, ll);
    ll find_(ll);
    void krus();
    void onion(ll, ll);
    
    int main() {
        memset(head, -1, sizeof(head));
    	ios::sync_with_stdio(false);
    	#ifdef ZZCAKIOI
    	#endif
        cin >> N >> M;
        for (ll i = 1; i <= M; i++) cin >> e[i].x >> e[i].y >> e[i].v;
        for (ll i = 1; i <= N; i++) fa[i] = i, siz[i] = 1;
        krus();
        dfs(1, 0);
        ll ans = INF;
        for (ll i = 1; i <= M; i++) {
            if (vis[i]) continue;
            zt now = lca(e[i].x, e[i].y);
            if (e[i].v == now.m1) ans = min(W - now.m2 + e[i].v, ans);
            else ans = min(W - now.m1 + e[i].v, ans);
        }
        cout << ans << '
    ';
    	return 0;
    }
    
    zt lca(ll x, ll y) {
        zt ret = {0, 0, 0};
        if (dep[x] < dep[y]) swap(x, y);
        ll di = dep[x] - dep[y];
        for (ll i = 20; ~i; i--) {
            if ((di >> i) & 1) {
                q[0] = dis[x][0][i], q[1] = dis[x][1][i];
                q[2] = ret.m1, q[3] = ret.m2;
    		    sort(q, q+4);
    		    tq = unique(q, q+4) - q;
                ret.m1 = q[tq-1], ret.m2 = q[tq-2];
                x = f[x][i];
            }
        }
        if (x == y) return ret;
        for (ll i = 20; ~i; i--) {
            if (f[x][i] != f[y][i]){
                q[0] = dis[x][0][i], q[1] = dis[x][1][i];
                q[2] = ret.m1, q[3] = ret.m2;
    		    sort(q, q+4);
    		    tq = unique(q, q+4) - q;
    		    ret.m1 = q[tq-1], ret.m2 = q[tq-2];
                q[0] = ret.m1, q[1] = ret.m2;
                q[2] = dis[y][0][i], q[3] = dis[y][1][i];
    		    sort(q, q+4);
    		    tq = unique(q, q+4) - q;
                ret.m1 = q[tq-1], ret.m2 = q[tq-2];
                x = f[x][i], y = f[y][i];
            }
        }
        q[0] = dis[x][0][0], q[1] = dis[x][1][0];
        q[2] = ret.m1, q[3] = ret.m2;
        sort(q, q+4);
        tq = unique(q, q+4) - q;
        ret.m1 = q[tq-1], ret.m2 = q[tq-2];
        q[2] = dis[y][0][0], q[3] = dis[y][1][0];
        q[1] = ret.m1, q[0] = ret.m2;
        sort(q, q+4);
        tq = unique(q, q+4) - q;
        ret.m1 = q[tq-1], ret.m2 = q[tq-2];
        return ret;
    }
    
    void dfs(ll n, ll ff) {
        dep[n] = dep[ff] + 1;
        f[n][0] = ff;
        for (ll i = 1; i <= 20; i++) {
            f[n][i] = f[f[n][i-1]][i-1];
            q[0] = dis[n][0][i-1], q[1] = dis[n][1][i-1];
            q[2] = dis[f[n][i-1]][0][i-1], q[3] = dis[f[n][i-1]][1][i-1];
            sort(q, q+4);
            tq = unique(q, q+4) - q;
            dis[n][0][i] = q[tq-1], dis[n][1][i] = q[tq-2];
        }
        for (ll i = head[n]; ~i; i = E[i].nt) {
            ll v = E[i].to;
            if (v == ff) continue;
            else {
                dis[v][0][0] = E[i].v;
                dfs(v, n);
            }
        }
    }
    
    void krus() {
        sort(e+1, e+M+1);
        for (ll i = 1, ct = 0; i <= M && ct < N-1; i++) {
            ll fx = find_(e[i].x), fy = find_(e[i].y);
            if (fx != fy) {
                onion(fx, fy), ct++, W += e[i].v;
                add(e[i].x, e[i].y, e[i].v);
                add(e[i].y, e[i].x, e[i].v);
                vis[i] = 1;
            }
        }
    }
    
    void onion(ll x, ll y) {
        ll fx = find_(x), fy = find_(y);
        if (siz[fx] < siz[fy]) fa[fx] = fy, siz[fx] += siz[fy];
        else fa[fy] = fx, siz[fy] += siz[fx];
    }
    
    void add(ll x, ll y, ll v) {E[++cnt] = {head[x], y, v}, head[x] = cnt;}
    ll find_(ll x) {return fa[x] == x ? x : fa[x] = find_(fa[x]);}
    
  • 相关阅读:
    用Jmeter完成性能测试
    Android Activity之间跳转和参数传递
    Android的四大组件
    REST服务和HTTP Headers
    移动端接口测试
    Android测试框架:Espresso
    HTML引用—180227
    HTML样式—180226
    HTML段落-180226
    HTML标题——180226
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13732184.html
Copyright © 2020-2023  润新知