C135 线段树分治+并查集 P5631 最小mex生成树
视频链接:C135 线段树分治 P5631 最小mex生成树_哔哩哔哩_bilibili
P5631 最小mex生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 线段树分治 O(nlognlogw) #include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define ls (u<<1) #define rs (u<<1|1) #define mid (l+r>>1) #define N 2000005 int n,m,mx,top; int a[N],b[N],w[N]; int p[N],siz[N]; vector<int>tr[400005]; //节点 struct node{ int x,y; }st[N<<1]; //栈 void insert(int u,int l,int r,int L,int R,int i){ if(l>R||r<L) return; if(L<=l&&r<=R) return tr[u].push_back(i); insert(ls,l,mid,L,R,i); insert(rs,mid+1,r,L,R,i); } int find(int x){ //查找根 return p[x]==x?x:find(p[x]); } void merge(int x,int y){ //合并集合 x=find(x),y=find(y); if(x==y) return; if(siz[x]>siz[y]) swap(x,y); st[++top]={x,y}; p[x]=y; siz[y]+=siz[x]; } void solve(int u,int l,int r){ int now=top; for(auto i:tr[u]) merge(a[i],b[i]); if(l==r){ if(siz[find(1)]==n) printf("%d\n",l),exit(0); } else solve(ls,l,mid),solve(rs,mid+1,r); while(top>now){ //撤销合并 node s=st[top--]; p[s.x]=s.x; siz[s.y]-=siz[s.x]; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) p[i]=i,siz[i]=1; for(int i=1;i<=m;++i){ scanf("%d%d%d",&a[i],&b[i],&w[i]); mx=max(mx,w[i]+1); } for(int i=1;i<=m;++i){ insert(1,0,mx, 0,w[i]-1, i); insert(1,0,mx, w[i]+1,mx,i); } solve(1,0,mx); }
分类:
C 数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!