P4234-最小差值生成树【LCT】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P4234


1|1题目大意

给出n个点m条边的一张图。求一棵生成树使得最大边权减去最小边权最小。

1n5×104,1m2×105


1|2解题思路

按照边权排序,然后像魔法森林一样用LCT维护最小生成树就好了。

没啥别的,练练手而已。时间复杂度O(nlogn)


1|3code

#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; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14630469.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(49)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示