• P4180 【模板】严格次小生成树[BJWC2010]


    小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值)  这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

    Input

    第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

    Output

    包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

    Sample Input5 6 1 2 1 1 3 2 2 4 3 3 5 4 3 4 3 4 5 6

    Sample Output11Hint

     

    数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

    扪心自问,kruskal的本质是什么?

    贪心

    kruskal算法被证明,对于任何的u,v

    有u到v之间边权最大值小于等于u到v未选入的边的边权

    所以说,不严格次小生成树只要

    遍历每条未选的边(u,v,d),用它替换u和v之间的最大边即可


    现在我们的任务就是把不严格的不去掉

    为什么它不严格?

    因为

    u到v之间边权最大值小于等于u到v未选入的边的边权

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    #define ll long long
    const int M = 100000 + 5;
    const int ME = 6e5 + 10, P = 18;
    long long inf = 1e14;
    ll  mx[M][P+1], mi[M][P+1];
    int dep[M], anc[M][P+1], fa[M], tot, h[M]; 
    bool ban[ME], vis[M];
    struct edge{int v, w, nxt;}G[M<<1];
    struct node{int u, v, w, id;}g[ME];
    void add(int u, int v, int w){
        G[++tot].v =v, G[tot].nxt = h[u], G[tot].w = w, h[u] = tot;
    }
    bool cmp(node A, node B){
        return A.w < B.w;
    }
    int find(int u){return u == fa[u] ? u : fa[u] = find(fa[u]);}
    
    void dfs(int u, int f, int w){
        vis[u] = 1;
        dep[u] = dep[f] + 1;
        anc[u][0] = f, mx[u][0] = w, mi[u][0] = -inf;
        for(int p = 1; p <= P; p++){
            anc[u][p] = anc[anc[u][p-1]][p-1];
            mx[u][p] = max(mx[u][p-1], mx[anc[u][p-1]][p-1]);
            mi[u][p] = max(mi[u][p-1], mi[anc[u][p-1]][p-1]);
            if(mx[u][p-1] > mx[anc[u][p-1]][p-1])
                mi[u][p] = max(mi[u][p], mx[anc[u][p-1]][p-1]);
            else if(mx[u][p-1] < mx[anc[u][p-1]][p-1])
                mi[u][p] = max(mi[u][p], mx[u][p-1]);
        }
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(v == f)continue;
            dfs(v, u, G[i].w);
        }
    }
    int getlca(int u, int v){
        if(dep[u] < dep[v]) swap(u, v);
        int t = dep[u] - dep[v];
        for(int p = 0; t; t>>=1, p++)
            if(t&1) u = anc[u][p];
        if(u == v) return u;
        for(int p = P; p >= 0; p--)
            if(anc[u][p] != anc[v][p])
                u = anc[u][p], v = anc[v][p];
        return anc[u][0];
    }
    ll get(int u, int v, int w){
        ll ret = -inf;
        for(int p = P; p >= 0; p--)
            if(dep[anc[u][p]] >= dep[v]){
                if(w == mx[u][p]) ret = max(ret, mi[u][p]);
                else ret = max(ret, mx[u][p]);
                u = anc[u][p];
            }
        return ret;
    }
    int main(){
        long long ans = 0, ret = inf;
        int n, m, u, v, w;
        scanf("%d%d", &n,&m);
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d", &u, &v, &w);
            g[i] = (node){u, v, w, i};
        }
        memset(mx[1], 0x8f, sizeof(mx[1]));
        memset(mi[1], 0x8f, sizeof(mi[1]));
        sort(g+1, g+1+m, cmp);
        for(int i = 1; i <= n; i++) fa[i] = i;
        for(int i = 1; i <= m; i++){
            int u = g[i].u, v = g[i].v;
            if(find(u) == find(v)) continue;
            fa[find(u)] = find(v);
            ans += 1LL*g[i].w;
            add(u, v, g[i].w), add(v, u, g[i].w);
            ban[i] = 1;
        }
        dfs(1, 0, 0);
        for(int i = 1; i <= n; i++) if(!vis[i])return !puts("orz");
        for(int i = 1; i <= m; i++){
            if(ban[i])continue;
            int u = g[i].u, v = g[i].v;
            int lca = getlca(u, v);
            ll s = get(u, lca, g[i].w);
            ll p = get(v, lca, g[i].w);
            ret = min(ret, 1LL*g[i].w - max(s, p));
        }
        printf("%lld
    ", ans+ret);
        
    }
  • 相关阅读:
    分别改动Cube每一个面的贴图UV(Unity3D开发之十八)
    解决MAC下PHP连接MYSQL错误Warning: mysql_connect(): No such file or directory in conn.php
    什么是IaaS,PaaS和SaaS及其区别
    /lib/dracut/hooks/shutdown/30-dm-shutdown.sh
    openstack instance bootmgr is missing 问题 修复
    openStack aio nova service-list neutron ext-list
    CentOS7 iso封装语句
    開始EEPlat之旅
    重构摘要4_构筑測试体系
    线程及其创建的方式
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9831357.html
Copyright © 2020-2023  润新知