luogu 4234 最小差值生成树 LCT

感觉码力严重下降~

#include <bits/stdc++.h>
#define N 400006
#define inf 1000000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
multiset<int>S;
multiset<int>::iterator it;
struct Edge
{
    int u,v,c;
    Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
}e[N];
bool cmp(Edge a,Edge b)
{
    return a.c<b.c;
}
struct Union
{
    int p[N];
    void init()
    {
        for(int i=1;i<N;++i) p[i]=i;
    }
    int find(int x)
    {
        return p[x]==x?x:p[x]=find(p[x]);
    }
    int merge(int x,int y)
    {
        x=find(x),y=find(y);
        if(x!=y)
        {
            p[x]=y;
            return 1;
        }
        return 0;
    }
}ufs;
struct Link_Cut_Tree
{
    #define lson t[x].ch[0]
    #define rson t[x].ch[1]
    int sta[N];
    struct Node
    {
        int ch[2],f,min,id,val,rev;
    }t[N];
    int isrt(int x)
    {
        return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x);
    }
    int get(int x)
    {
        return t[t[x].f].ch[1]==x;
    }
    void pushup(int x)
    {
        t[x].min=t[x].val, t[x].id=x;
        if(lson && t[lson].min<t[x].min) t[x].min=t[lson].min,t[x].id=t[lson].id;
        if(rson && t[rson].min<t[x].min) t[x].min=t[rson].min,t[x].id=t[rson].id;
    }
    void mark(int x)
    {
        if(x) t[x].rev^=1,swap(lson,rson);
    }
    void pushdown(int x)
    {
        if(t[x].rev)
        {
            if(lson) mark(lson);
            if(rson) mark(rson);
            t[x].rev=0;
        }
    }
    void rotate(int x)
    {
        int old=t[x].f,fold=t[old].f,which=get(x);
        if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x;
        t[old].ch[which]=t[x].ch[which^1], t[t[old].ch[which]].f=old;
        t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;
        pushup(old),pushup(x);
    }
    void splay(int x)
    {
        int v=0,u=x,fa;
        for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f;
        for(;v;--v) pushdown(sta[v]);
        for(u=t[u].f;(fa=t[x].f)!=u;rotate(x))
            if(t[fa].f!=u)
                rotate(get(fa)==get(x)?fa:x);
    }
    void Access(int x)
    {
        for(int y=0;x;y=x,x=t[x].f)
            splay(x),rson=y,pushup(x);
    }
    void makeroot(int x)
    {
        Access(x),splay(x),mark(x);
    }
    void link(int x,int y)
    {
        makeroot(x),t[x].f=y;
    }
    void cut(int x,int y)
    {
        makeroot(x),Access(y),splay(y);
        t[t[y].ch[0]].f=0;
        t[y].ch[0]=0;
        pushup(y);
    }
    void split(int x,int y)
    {
        makeroot(x),Access(y),splay(y);
    }
    #undef lson
    #undef rson
}op;
int main()
{
    int i,j,n,m,ans=inf;
    // setIO("input");
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
    sort(e+1,e+1+m,cmp);
    ufs.init();
    for(i=1;i<=n;++i) op.t[i].val=inf;
    for(i=1;i<=m;++i)
    {
        int x=e[i].u,y=e[i].v,c=e[i].c,_new=i+n;
        if(x==y) continue;
        if(ufs.merge(x,y))
        {
            op.t[_new].val=c;
            op.link(x,_new);
            op.link(_new,y);
            S.insert(c);
        }
        else
        {
            op.split(x,y);
            if(op.t[y].min<c)
            {
                S.erase(S.find(op.t[y].min));
                S.insert(c);
                int kk=op.t[y].id;
                int xx=e[kk-n].u;
                int yy=e[kk-n].v;
                op.cut(xx,kk);
                op.cut(yy,kk);
                op.t[_new].val=c;
                op.link(x,_new);
                op.link(_new,y);
            }
        }
        if(S.size()>=n-1)
        {
            it=S.end();
            it--;
            ans=min(ans,*(it)-*(S.begin()));
        }
    }
    printf("%d\n",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11580745.html

时间: 2024-10-09 12:17:07

luogu 4234 最小差值生成树 LCT的相关文章

洛谷.4234.最小差值生成树(LCT)

题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树上最小边的权值. LCT上维护最小边的编号.求最小边把树上的边用vis[]标记即可. 不熟啊. (另外暴力可以排序后枚举一个分界点,在它之后求最小生成树,在它之前求最大生成树) #include <cstdio> #include <cctype> #include <algor

luogu4234 最小差值生成树

题目大意 在一个带权无向图中,它的最小差值生成树为最大边与最小边差值最小的生成树.求一个图的最小差值生成树. 题解 30分解法 引理1 最小生成树的最大边的边权是所有生成树中最大边边权中的最小值. 证明:任意一棵生成树都可以在最小生成树的基础上,通过不断取一个树外边e,将其替换掉其与生成树所在环中的一条边的方式而得到.我们就看看第一条用来替换的边的情况吧.在不在最小生成树中的边中任取一个边权小于最小生成树最大边m的边e,则e必然与最小生成树的树边形成环.若m不在环中,那么就是替换掉任意一条边,答

洛谷P4234 最小差值生成树【LCT】

题目描述 给定一个标号为从 1 到 n 的.有 m 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入格式: 第一行两个数 n, m ,表示图的点和边的数量. 第二行起 m 行,每行形如$ u_i, v_i, w_i$ ,代表 $u_i$ 到 $v_i$有一条长为 $w_i$的无向边. 输出格式: 输出一行一个整数,代表你的答案. 数据保证存在至少一棵生成树. 输入样例#1: 4 6 1 2 10 1 3 100 1 4 90 2 3 20 2 4 80 3 4 40 输出样例#1:

luoguP4234 最小差值生成树

https://www.luogu.org/problemnew/show/P4234 按照边的权值从小到大排序,依次加入,并删除能够删除的权值最小的一条边,用 set 维护当前所有边的边权,并查集维护联通性,LCT 维护两点间最小值和 link cut 操作即可 #include <bits/stdc++.h> #define mp make_pair using namespace std; typedef unsigned long long ull; typedef long long

POJ 3552 Slim Span (最小差值生成树)

链接:http://poj.org/problem?id=3522 题意:给你N个点,M条边(无向的):让你求一个生成树它具有:最大边权与最小边权的差是最小的. 分析:使用kru算法求生成树:当我们用最小边求取了生成树后,去除最小边,继续再求生成树,只需要每次求完生成树后跟新答案就可以了:复杂度O(M*M),因为边不多,可以实现. 1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include&l

笔试题:排序后取最小差值数

笔试题:要从5个人中选取2个人作为礼仪,其中每个人的身高范围为160-190,要求2个人的身高差值最小(如果差值相同的话,选取其中最高的两人),以升序输出两个人的身高. Smple input:161 189 167 172 188 Sample outPut: 188 189 public class demo06{ public static void main(String[] args){ int[] arr={161,189,167,172,188};//原始值 //将原始值升序排序

POJ 3264 Balanced Lineup(最大最小差值 线段树水题)

Language: Default Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 37122   Accepted: 17383 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order.

LeetCode-908. 最小差值 I

给定一个整数数组 A,对于每个整数 A[i],我们可以选择任意 x 满足 -K <= x <= K,并将 x 加到 A[i] 中. 在此过程之后,我们得到一些数组 B. 返回 B 的最大值和 B 的最小值之间可能存在的最小差值. 示例 1: 输入:A = [1], K = 0 输出:0 解释:B = [1] 示例 2: 输入:A = [0,10], K = 2 输出:6 解释:B = [2,8] 示例 3: 输入:A = [1,3,6], K = 3 输出:0 解释:B = [3,3,3] 或

【CCF】最小差值

问题描述: 问题描述 给定n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值. 输入格式 输入第一行包含一个整数n. 第二行包含n个正整数,相邻整数之间使用一个空格分隔. 输出格式 输出一个整数,表示答案. 样例输入 51 5 4 8 20 样例输出 1 样例说明 相差最小的两个数是5和4,它们之间的差值是1. 样例输入 59 3 6 1 3 样例输出 0 样例说明 有两个相同的数3,它们之间的差值是0. 数据规模和约定 对于所有评测用例,2 ≤ n ≤ 1000,每个给定