LCT 最小生成树

Posted zw130-lzr-blogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCT 最小生成树相关的知识,希望对你有一定的参考价值。

闲的无聊,常数大的惊人

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MN 700005
#define re register int
#define ll long long
using namespace std;
int f[MN],v[MN],s[MN],r[MN],son[MN][2];
int zhan[MN];
int n,m,cnt;
int get(int x)////判断节点是否为一个Splay的根(与普通Splay的区别1)
    return son[f[x]][0]==x||son[f[x]][1]==x;
////如果连的是轻边,他的父亲的儿子里没有它
void pushup(int x)
    s[x]=x;
    if(v[s[x]]<v[s[son[x][0]]])s[x]=s[son[x][0]];
    if(v[s[x]]<v[s[son[x][1]]])s[x]=s[son[x][1]];

void filp(int x)
    swap(son[x][0],son[x][1]);
    r[x]^=1;

void pushdown(int x)
    if(!r[x])return;
    r[x]=0;
    if(son[x][0])filp(son[x][0]);
    if(son[x][1])filp(son[x][1]);

void rotate(int x)
    int y=f[x],z=f[y],k=(son[y][1]==x),s=son[x][!k];
    if(get(y))son[z][son[z][1]==y]=x;son[x][!k]=y;son[y][k]=s;
    if(s)f[s]=y;f[y]=x;f[x]=z;
    pushup(y);

void splay(int x)
    int y=x,top=0;
    zhan[++top]=y;
    while(get(y))zhan[++top]=f[y],y=f[y];
    while(top)pushdown(zhan[top--]);
    while(get(x))
        y=f[x],top=f[y];
        if(get(y))
        rotate((son[y][0]==x)^(son[top][0]==y)?x:y);
        rotate(x);
    
    pushup(x);
    return;

void access(int x)
    for(re y=0;x;y=x,x=f[x])
    splay(x);
    son[x][1]=y;
    pushup(x);
    

void makeroot(int x)
    access(x);
    splay(x);
    filp(x);

int findroot(int x)    
    access(x);
    splay(x);
    while(son[x][0])pushdown(x),x=son[x][0];
    splay(x);
    return x;

void split(int x,int y)
    makeroot(x);
    access(y);
    splay(y);

void link(int x,int y)
    makeroot(x);
    if(findroot(y)!=x)f[x]=y;

void cut(int x)
//对cut进行%改
    splay(x);
    f[son[x][0]]=f[son[x][1]]=0;

int main()
    scanf("%d%d",&n,&m);
    int ans=0;
    for(re i=1;i<=m;i++)
        int a1,a2,a3;
        scanf("%d%d%d",&a1,&a2,&a3);
        v[i+n]=a3;
        makeroot(a1);
        if(findroot(a2)!=a1)link(a1,i+n),link(i+n,a2),ans+=a3;
        else
        split(a1,a2);
        int now=s[a2];
        if(v[now]<=a3)continue;
        ans-=(v[now]-a3);
        cut(now);
        link(a1,i+n);
        link(i+n,a2);


    printf("%d\n",ans);
    return 0;

  

 

以上是关于LCT 最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

3669 [Noi2014]魔法森林(LCT,最小生成树)

LCT 最小生成树

洛谷P4234 最小差值生成树LCT

洛谷P4172 [WC2006]水管局长 (LCT,最小生成树)

luogu 4234 最小差值生成树 LCT

BZOJ 3669 [Noi2014]魔法森林 LCT维护动态最小生成树