P4234-最小差值生成树【LCT】
正题
题目链接:https://www.luogu.com.cn/problem/P4234
题目大意
给出\(n\)个点\(m\)条边的一张图。求一棵生成树使得最大边权减去最小边权最小。
\(1\leq n\leq 5\times 10^4,1\leq m\leq 2\times 10^5\)
解题思路
按照边权排序,然后像魔法森林一样用\(LCT\)维护最小生成树就好了。
没啥别的,练练手而已。时间复杂度\(O(n\log n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int N=3e5+10;
struct node{
int x,y,w;
}e[N];
int n,m,p[N],fa[N];bool v[N];
struct LCT{
int fa[N],t[N][2];
bool r[N];stack<int> s;
bool Nroot(int x)
{return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}
bool Direct(int x)
{return t[fa[x]][1]==x;}
void PushUp(int x)
{p[x]=min(min(p[t[x][0]],p[t[x][1]]),x);return;}
void Rev(int x)
{r[x]^=1;swap(t[x][0],t[x][1]);return;}
void PushDown(int x)
{if(r[x])Rev(t[x][0]),Rev(t[x][1]),r[x]=0;return;}
void Rotate(int x){
int y=fa[x],z=fa[y];
int xs=Direct(x),ys=Direct(y);
int w=t[x][xs^1];
t[y][xs]=w;t[x][xs^1]=y;
if(Nroot(y))t[z][ys]=x;
if(w)fa[w]=y;fa[y]=x;fa[x]=z;
PushUp(y);PushUp(x);return;
}
void Splay(int x){
int y=x;s.push(x);
while(Nroot(y))y=fa[y],s.push(y);
while(!s.empty())PushDown(s.top()),s.pop();
while(Nroot(x)){
int y=fa[x];
if(!Nroot(y))Rotate(x);
else if(Direct(x)==Direct(y))
Rotate(y),Rotate(x);
else Rotate(x),Rotate(x);
}
return;
}
void Access(int x){
for(int y=0;x;y=x,x=fa[x])
Splay(x),t[x][1]=y,PushUp(x);
return;
}
void MakeRoot(int x)
{Access(x);Splay(x);Rev(x);return;}
int Split(int x,int y)
{MakeRoot(x);Access(y);Splay(y);return p[y];}
void Link(int x,int y)
{MakeRoot(x);fa[x]=y;Access(x);return;}
void Cut(int x,int y)
{MakeRoot(x);Access(y);Splay(y);fa[t[y][0]]=0;t[y][0]=0;PushUp(y);return;}
}T;
int find(int x)
{return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
bool cmp(node x,node y)
{return x.w<y.w;}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
sort(e+1,e+1+m,cmp);
memset(p,0x3f,sizeof(p));
for(int i=1;i<=n+m;i++)fa[i]=p[i]=i;
int k=n,z=0,ans=1e5;
for(int i=1;i<=m;i++){
int x=e[i].x,y=e[i].y;
if(x==y)continue;
int fx=find(x),fy=find(y);
if(fx==fy){
int num=T.Split(x+m,y+m);
T.Cut(e[num].x+m,num);
T.Cut(num,e[num].y+m);
v[num]=0;
}
else fa[fx]=fy,k--;
T.Link(x+m,i);T.Link(i,y+m);
v[i]=1;while(!v[z])z++;
if(k==1)ans=min(ans,e[i].w-e[z].w);
}
printf("%d\n",ans);
return 0;
}
P4234-最小差值生成树【LCT】的更多相关文章
- P4234 最小差值生成树 LCT维护边权
\(\color{#0066ff}{ 题目描述 }\) 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. \(\color{#0 ...
- 洛谷 P4234 最小差值生成树(LCT)
题面 luogu 题解 LCT 动态树Link-cut tree(LCT)总结 考虑先按边权排序,从小到大加边 如果构成一颗树了,就更新答案 当加入一条边,会形成环. 贪心地想,我们要最大边权-最小边 ...
- P4234 最小差值生成树
题目 P4234 最小差值生成树 做法 和这题解法差不多,稍微变了一点,还不懂就直接看代码吧 \(update(2019.2):\)还是具体说一下吧,排序,直接加入,到了成环情况下,显然我们要把此边代 ...
- 洛谷.4234.最小差值生成树(LCT)
题目链接 先将边排序,这样就可以按从小到大的顺序维护生成树,枚举到一条未连通的边就连上,已连通则(用当前更大的)替换掉路径上最小的边,这样一定不会更差. 每次构成树时更新答案.答案就是当前边减去生成树 ...
- 洛谷P4234 最小差值生成树(lct动态维护最小生成树)
题目描述 给定一个标号为从 11 到 nn 的.有 mm 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式: 第一行两个数 n, mn,m ,表示图的点和边的数量. ...
- 【Luogu】P4234最小差值生成树(LCT)
题目链接 能把LCT打得每个函数都恰有一个错误也是挺令我惊讶的. 本题使用LCT维护生成树,具体做法是对原图中的每个边建一个点,然后连边的时候相当于是将边的起点跟“边”这个点连起来,边的终点也跟它连起 ...
- 洛谷P4234 最小差值生成树(LCT,生成树)
洛谷题目传送门 和魔法森林有点像,都是动态维护最小生成树(可参考一下Blog的LCT总结相关部分) 至于从小到大还是从大到小当然无所谓啦,我是从小到大排序,每次枚举边,还没连通就连,已连通就替换环上最 ...
- 【刷题】洛谷 P4234 最小差值生成树
题目描述 给定一个标号为从 \(1\) 到 \(n\) 的.有 \(m\) 条边的无向图,求边权最大值与最小值的差值最小的生成树. 输入输出格式 输入格式: 第一行两个数 \(n, m\) ,表示图的 ...
- Luogu P4234 最小差值生成树
题意 给定一个 \(n\) 个点 \(m\) 条边的有权无向图,求出原图的一棵生成树使得该树上最大边权与最小边权的差值最小. \(\texttt{Data Range:}1\leq n\leq 5\t ...
- [洛谷P4234] 最小差值生成树
题目类型:\(LCT\)动态维护最小生成树 传送门:>Here< 题意:求一棵生成树,其最大边权减最小边权最小 解题思路 和魔法森林非常像.先对所有边进行排序,每次加边的时候删除环上的最小 ...
随机推荐
- docker-compose部署mysql,redis,rabbitmq
version: '3' services: mysql: image: mysql:5.7.31 container_name: mysql restart: always command: --c ...
- 【springboot】 junit 测试
参考:https://blog.csdn.net/u012100371/article/details/77206863 @RunWith(SpringJUnit4ClassRunner.class) ...
- 2014 12 27 bestcoder 第一题
水的不行不行的一道题 也是自己做的第一道题 纪念下 1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h ...
- 使用volatile的条件
使用volatile的值不能依赖于它之前的值: volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果. ...
- java 循环移位输出全排列
//题目:利用1.2.2.3.4这4个数字,用java写一个main函数打印出所有不同的排列,如12234,,2234等,要求打印出来不能有重复 1 package test123; 2 3 impo ...
- docker《三》单机部署项目容器,nginx负载均衡
接着<二> 创建一个网段(和二在一个网段) docker network create --subnet=172.19.0.0/24 pro-net docker run -d --nam ...
- 浅谈Java和Go的程序退出
前言 今天在开发中对Java程序的退出产生了困惑,因为题主之前写过一段时间Go,这两者的程序退出逻辑是不同的,下面首先给出结论,再通过简单的例子来介绍. 对于Java程序,Main线程退出,如果当前存 ...
- vue-父子组件之传值和单项数据流问题
前言 我们知道 vue 中父子组件的核心概念是单项数据流问题,props 是单项传递的.那究竟什么是单项数据流问题,这篇文章来总结一下关于这个知识点的学习笔记. 正文 1.父组件传值给子组件 < ...
- vue 引用省市区三级联动(element-ui Cascader)
npm 下载 npm install element-china-area-data -S main.js import {provinceAndCityData,regionData,provinc ...
- Leetcode 146. LRU 缓存机制
前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...