码迷,mamicode.com
首页 > 其他好文 > 详细

严格最小生成树

时间:2019-11-11 00:55:39      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:main   dig   例题   space   inf   生成树   模板   大于   out   

原理简介

非严格次小生成树是在最小生成树有多棵时未被选为最小生成树的树,而严格最小生成树要求其边权和是第一个大于最小生成树的边权和。两者算法大致相同,都是枚举非树边加入树中,很明显会形成一棵基环树,在基环的环(不包含加入的边)中找出最大值被加入边代替更新答案,只是单纯找最大得到非严格,而找出第一个严格小于加入边权值的边得到的是严格次小生成树(被相同权值的边替换边权和不会变大哦~~~)。

例题Luogu-P4180

模板题

#include <iostream> 
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>  
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
template<typename xxx>inline void read(xxx &x) {
    int f = 1;char c = getchar();x = 0;
    for(;c ^ '-' && !isdigit(c);c = getchar());
    if(c == '-') f = -1,c = getchar();
    for(;isdigit(c);c = getchar()) x = (x<<3) + (x<<1) + (c ^ '0');
    x *= f;
} 
template<typename xxx>inline void print(xxx x) {
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
const int maxn = 1000010;
const int mod = 998244353;
const int inf = 0x7fffffff;
struct node{
    int a,b;ll c;
}g[maxn];
inline bool gmp(node x,node y) {
    return x.c < y.c;
}
struct edge {
    int to,last;
    ll val;
}e[maxn<<1];
int head[maxn],tot;
inline void add(int from,int to,ll val) { 
    ++tot;
    e[tot].to = to;
    e[tot].val = val;
    e[tot].last = head[from];
    head[from] = tot;
} 
int n,m,s;
int w[maxn],cnt;
int dad[maxn];
int dep[maxn];
int rev[maxn];
int seg[maxn];
int siz[maxn];
int son[maxn];
int top[maxn];
inline void ddfs1(int x,int da) {
    siz[x] = 1;dad[x] = da;
    dep[x] = dep[da] + 1;
    for(rint i = head[x];i;i = e[i].last) {
        if(e[i].to == da) continue;
        ddfs1(e[i].to,x);
        siz[x] += siz[e[i].to];
        if(son[x] == 0 || siz[son[x]] < siz[e[i].to]) son[x] = e[i].to; 
    }
    return ;
}
inline void ddfs2(int x,int tp) {
    seg[x] = ++cnt;
    rev[cnt] = x;
    top[x] = tp;
    if(!son[x]) return ;
    ddfs2(son[x],tp);
    for(rint i = head[x];i;i = e[i].last) {
        if(e[i].to == dad[x] || e[i].to == son[x]) continue;
        ddfs2(e[i].to,e[i].to);
    }
    return ;
}
ll sum,mks[maxn<<2],sec[maxn<<2];
inline void pushup(int x) {
    mks[x] = max(mks[lson],mks[rson]);
    if(mks[lson] == mks[rson]) sec[x] = max(sec[lson],sec[rson]);
    else sec[x] = min(mks[lson],mks[rson]);
    return ;
}
inline void update(int x,int L,int R,int pos,ll val) {
    if(L == R) {
        mks[x] = val;
        sec[x] = -1e17;
        return;
    } 
    if(pos <= mid) update(lson,L,mid,pos,val);
    else update(rson,mid + 1,R,pos,val);
    pushup(x);
    return ;
}
inline ll qmax(int x,int L,int R,int l,int r,ll val) {
    if(l <= L && R <= r) {
        if(val == mks[x]) return sec[x];
        else return mks[x];
    }
    ll ans = 0;
    if(l <= mid) ans = max(ans,qmax(lson,L,mid,l,r,val));
    if(r >  mid) ans = max(ans,qmax(rson,mid + 1,R,l,r,val));
    return ans;
}
inline ll q1(int x,int y,ll val) {
    ll ans = 0;
    while(top[x] ^ top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x,y);
        ans = max(ans,qmax(1,1,n,seg[top[x]],seg[x],val));
        x = dad[top[x]];
    }
    if(x ^ y) {
        if(dep[x] > dep[y]) swap(x,y);
        ans = max(ans,qmax(1,1,n,seg[son[x]],seg[y],val));
    } 
    return ans;
}
int fa[maxn];
inline int f(int x) {
    while(x ^ fa[x]) x = fa[x] = fa[fa[x]];
    return x;
}
int vis[maxn];
int main() {
    ll cnm = 1e17;
    read(n);read(m);
    for(rint i = 1;i <= n; ++i) fa[i] = i; 
    for(rint i = 1;i <= m; ++i) {
        read(g[i].a);
        read(g[i].b);
        read(g[i].c);
    }
    stable_sort(g + 1,g + m + 1,gmp); 
    for(rint i = 1;i <= m; ++i) {
        int x = f(g[i].a);
        int y = f(g[i].b);
        if(x ^ y) {
            fa[x] = y;sum += g[i].c;
            add(g[i].a,g[i].b,g[i].c);
            add(g[i].b,g[i].a,g[i].c);
        } else {
            vis[i] = 1;
        }
    }
    ddfs1(1,0);
    ddfs2(1,1);
    for(rint i = 1;i <= m; ++i) {
        if(!vis[i]) {
            if(dep[g[i].a] > dep[g[i].b]) {
                update(1,1,n,seg[g[i].a],g[i].c);
            } else {
                update(1,1,n,seg[g[i].b],g[i].c);
            }
        }
    }
    for(rint i = 1;i <= m; ++i) {
        if(vis[i]) {
            ll fk = q1(g[i].a,g[i].b,g[i].c);
            ll tem = sum - fk + g[i].c;
            if(tem ^ sum && tem < cnm) cnm = tem;
//          cout<<tem<<" "<<sum<<" "<<fk<<endl;
        }
    }
    print(cnm);
    return 0;
}
/*

*/

严格最小生成树

标签:main   dig   例题   space   inf   生成树   模板   大于   out   

原文地址:https://www.cnblogs.com/Thomastine/p/11832316.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!