Codeforces 455C. Civilization (树的直径+并查集)
来源:互联网 发布:宇宙数控系统编程 编辑:程序博客网 时间:2024/05/18 18:03
题目描述
传送门
题目大意:
(1)询问x所在连通块的最长链
(2)将x,y所在的连通块合并,任意两个点之间可以连边,使合并后连通块的最长链最短。
题解
比较容易想到的是连接的两个点是两棵树的中心(最长链的中点)。
关键是连接后的树中点是否会改变呢?答案是连接后的中心是两棵树中最长链较长的树的中心。
那么我们把一个连通块的代表元素维护成树的中心,在这个点动态维护经过这个点子树中的最长链和次长链。
那么对于询问,就是找到代表元素求最长链和次长链的和。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 600003using namespace std;int tot,head,p[N],n,m,q,top,st[N],ans,ansx;int point[N],v[N],nxt[N],pre[N],fa[N],pd[N],val[N],f[N],g[N];void add(int x,int y){ tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void dfs(int x,int f,int d){ st[++top]=x; pd[x]=1; if (d>ans) { ans=d; ansx=x; } for (int i=point[x];i!=-1;i=nxt[i]){ if (v[i]==f) continue; pre[v[i]]=i; dfs(v[i],x,d+1); }}int getroad(int x,int y){ head=0; while (x!=y) { p[++head]=x; x=v[pre[x]^1]; } p[++head]=x; return p[(head+1)/2];}int find(int x){ if (fa[x]==x) return x; fa[x]=find(fa[x]); return fa[x];}int main(){ freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d%d%d",&n,&m,&q); tot=-1; memset(point,-1,sizeof(point)); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); } for (int i=1;i<=n;i++) fa[i]=i; for (int i=1;i<=n;i++) if (!pd[i]) { ansx=ans=-1; dfs(i,0,0); int t=ansx; ansx=ans=-1; top=0; dfs(t,0,0); int mid=getroad(ansx,t); val[mid]=ans; f[mid]=ans/2; g[mid]=ans-f[mid]; if (f[mid]<g[mid]) swap(f[mid],g[mid]); for (int j=1;j<=top;j++) fa[st[j]]=mid; } for (int i=1;i<=q;i++) { int opt,x,y; scanf("%d%d",&opt,&x); if (opt==1) { x=find(x); printf("%d\n",val[x]); } else { scanf("%d",&y); int r1=find(x); int r2=find(y); if (r1==r2) continue; if (val[r1]>val[r2]) { fa[r2]=r1; if (f[r2]+1>f[r1]) g[r1]=f[r1],f[r1]=f[r2]+1; else g[r1]=max(f[r2]+1,g[r1]); val[r1]=g[r1]+f[r1]; } else { fa[r1]=r2; if(f[r1]+1>f[r2]) g[r2]=f[r2],f[r2]=f[r1]+1; else g[r2]=max(g[r2],f[r1]+1); val[r2]=f[r2]+g[r2]; } } }}
阅读全文
0 0
- Codeforces 455C Civilization 树的直径+并查集
- 【树的直径+并查集】 codeforces 455C - Civilization
- CodeForces 455C Civilization(并查集+树直径)
- Codeforces 455C. Civilization (树的直径+并查集)
- codeforces 455C C. Civilization(树形dp+树的直径+并查集)
- 【打CF,学算法——四星级】CodeForces 455C Civilization (【详解】并查集+树的直径)
- Codeforces 455E Civilization【思维+树的直径+并查集】
- codeforces round260 div1C&div2E Civilization 并查集+树的直径
- Codeforces 455C Civilization(并查集+树形dp)
- codeforces 455C Civilization 树的最长链+并查集
- 【CodeForces】445C Civilization 并查集
- Codeforces 455C Civilization(并查集+dfs)
- Codeforces 455C Civilization(并查集+dfs)
- Codeforces 455C —— Civilization(并查集,树上最长链)
- codeforces 466C Civilization 并查集+dfs
- Codeforces Round #260 (Div. 1)C题(并查集+树的直径)
- coderforces 455C 并查集+树的直径
- CF455C Civilization (并查集)
- 写给Android App开发人员看的Android底层知识(6)
- java 基于socket套接字的低层次网络编程
- 多条Shell命令的组合连接
- USACO-Section1.1 Greedy Gift Givers[...]
- 219. Contains Duplicate II 答案
- Codeforces 455C. Civilization (树的直径+并查集)
- JS斩杀LeetCode(1):Two Sum
- swift-oc 交互记录
- TCP的定时器系列 — SYNACK定时器
- 内部类的闭包与回调
- 用ffmpeg+qt做点有趣的事(3)----- ffmpeg解码流程
- SVN Unable to connect to a repository at URL
- 用python抓取百万网易云热门评论[转载]
- 搜索-B