zoukankan      html  css  js  c++  java
  • 4234最小差值生成树

    有点巧妙啊!

    s[x]每次维护的是最小值

    我们将边按从大到小排个序,这样编号小的就在前面啦!QAQ

    再按最小生成树的LCT的做法来

    不过我们每次要用一个book标记前面最小边的编号

    每次要更新答案时,一直往前跳,跳到最晚更新的即使最小的

    我口胡的,错了请dalao指出

    #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 book[MN];
    int ltk;
    struct tu{
        int u,v,w;
    }e[MN];
    bool comp(tu p,tu q){
        return p.w<q.w;
    }
    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(s[son[x][0]]> n && (s[x]<= n ||s[x]>s[son[x][0]] ) ) s[x]=s[son[x][0]];
        if(s[son[x][1]]> n && (s[x]<= n ||s[x]>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 pos=1;
        int ans=0x7fffffff;
        int now=0;
        for(re i=1;i<=m;i++)
        {
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        }
        sort(e+1,e+1+m,comp);
        for(re i=1;i<=m;i++){
            int x=e[i].u,y=e[i].v;
            if(x==y){book[i]=1;continue;}
            makeroot(x);
            if(findroot(y)!=x)link(e[i].u,i+n),link(i+n,e[i].v),++ltk;
            else{        
                split(x,y);
                now=s[y];
                book[now-n]=1;
                cut(now);
                link(x,n+i);
                link(n+i,y);
            }
            while(book[pos]&&pos<=i)++pos;
            if(ltk>=n-1)ans=min(ans,e[i].w-e[pos].w);
    }
        printf("%d
    ",ans);
        return 0;
    }
    缘分让我们相遇乱世以外, 命运却要我们危难中相爱。 也许未来遥远在光年之外, 我愿守候未知里为你等待。
  • 相关阅读:
    中值定理
    poj 3984 迷宫问题 bfs
    android 处理网络状态——无网,2g,3g,wifi,ethernet,other
    POJ 1273 || HDU 1532 Drainage Ditches (最大流模型)
    Android硬件加速
    Android的横竖屏切换
    滑雪_poj_1088(记忆化搜索).java
    Rank of Tetris(hdu1811拓扑排序+并查集)
    git在windows下clone、pull或者push内存溢出的解决办法
    数据库中DDL、DML、DCL和TCP概念
  • 原文地址:https://www.cnblogs.com/zw130-lzr-blogs/p/11220601.html
Copyright © 2011-2022 走看看