CF455C. Civilization-并查集
2100分的并查集(x)
link:https://codeforces.com/contest/455/problem/C
给一张无向森林,有若干次操作,有两种:
- 询问
所在树的直径 - 合并
所在的连通块,使得合并后的直径最小
处理出每个连通块的直径,考虑如何合并两个连通块?设原来的直径分别是
直径的信息可以用并查集维护
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define endl '\n' #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=3e5+5; int n,m,q,c; int fa[N],len[N],dep[N]; vector<vector<int>> G; int find(int x){ if(fa[x]==x)return x; return fa[x]=find(fa[x]); } void merge(int x,int y){ int fx=find(x),fy=find(y); if(fx==fy)return; int L1=len[fx],L2=len[fy]; len[fx]=max({L1,L2,1+(L1+1)/2+(L2+1)/2}); fa[fy]=fx; } void dfs(int x,int fa){ for(auto to:G[x])if(to!=fa){ dep[to]=dep[x]+1; if(dep[to]>dep[c])c=to; dfs(to,x); } } int main(){ fastio; cin>>n>>m>>q; rep(i,1,n)fa[i]=i; G=vector<vector<int>>(n+1); while(m--){ int a,b; cin>>a>>b; G[a].push_back(b); G[b].push_back(a); merge(a,b); } rep(i,1,n)if(find(i)==i){ int L,R; c=0; dfs(i,-1); L=c; dep[c]=0; dfs(c,-1); R=c; len[i]=dep[R]-dep[L]; } while(q--){ int op,x,y; cin>>op>>x; if(op==1)cout<<len[find(x)]<<endl; else{ cin>>y; merge(x,y); } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律