CodeForces 455C Civilization(并查集+树直径)
来源:互联网 发布:考勤系统设计sql 编辑:程序博客网 时间:2024/05/18 00:06
好久没有写过图论的东西了,居然双向边要开两倍空间都忘了,不过数组越界cf居然给我报MLE??这个题题意特别纠结,一开始一直不懂添加的边长是多长。。。
题意:给你一些点,然后给一些边,注意没有重边 环,接着给你两种操作:
1 x :求出 x 的集合中最长的边权值
2 x y:合并 x 的集合和 y的集合变成一个集合,并且将 x 集合中任意一个点与 y 集合中任意一个点相连,使合成的集合的任意两个点的最大权值最小,其中两个点相连的权值为1
开始边是固定的,因而建图并两次dfs遍历找树直径,但是不一定所有点是在连一起的所以要找扫一遍。
树直径:无根树中某两个点的距离的最大值,第一遍dfs,以任意一点为起点找到距离最远的点,接着以找到的点起点再来一遍dfs
接着使用并查集,合并两棵树更新权值:(ran[x]+1)/2+(ran[y]+1)/2+1(合并后 两树之间 可以形成的最大权值的最小值)
#include<set>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#include<string>#include<cstdio>#include<cstring>#include<stdlib.h>#include<iostream>#include<algorithm>using namespace std;#define eps 1E-8/*注意可能会有输出-0.000*/#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0#define mul(a,b) (a<<b)#define dir(a,b) (a>>b)typedef long long ll;typedef unsigned long long ull;const int Inf=1<<28;const double Pi=acos(-1.0);const int Mod=1e9+7;const int Max=600010;//双向边,开两倍int fat[Max],ran[Max],vis[Max],len,ega;int head[Max],nnext[Max],to[Max],e;void Init(int n){ e=0; memset(head,-1,sizeof(head)); for(int i=0; i<=n; i++) { fat[i]=i; ran[i]=0; vis[i]=0; } return;}void add(int u,int v){ to[e]=v; nnext[e]=head[u]; head[u]=e++; return;}void dfs(int son,int fat,int now)//遍历树{ vis[son]=1; for(int i=head[son]; i!=-1; i=nnext[i]) { if(to[i]!=fat) dfs(to[i],son,now+1); } if(len<now)//找到最远的点 { len=now; ega=son; } return;}int Find(int x){ if(x==fat[x]) return fat[x]; return fat[x]=Find(fat[x]);}void Union(int x,int y){ int x1=Find(x); int y1=Find(y); if(x1==y1) return; if(x1>y1)//最小数字的得到权值 { fat[x1]=y1; ran[y1]=max(ran[x1],max(ran[y1],(ran[x1]+1)/2+(ran[y1]+1)/2+1));//两棵树合并得到的最小直径 } else { fat[y1]=x1; ran[x1]=max(ran[x1],max(ran[y1],(ran[x1]+1)/2+(ran[y1]+1)/2+1)); } return;}int main(){ int n,m,q; int u,v,typ; while(~scanf("%d %d %d",&n,&m,&q)) { Init(n); for(int i=0; i<m; i++) { scanf("%d %d",&u,&v); Union(u,v); add(u,v); add(v,u); } for(int i=1; i<=n; i++) //两次dfs求出树直径 { if(!vis[i]) { len=0; ega=i; dfs(i,i,0); len=0; dfs(ega,ega,0); ran[i]=len;//最小的点赋权值 } } for(int i=0; i<q; i++) { scanf("%d",&typ); if(typ==1) { scanf("%d",&u); v=Find(u); printf("%d\n",ran[v]); } else { scanf("%d %d",&u,&v); Union(u,v); } } } return 0;}
0 0
- CodeForces 455C Civilization(并查集+树直径)
- Codeforces 455C Civilization 树的直径+并查集
- 【树的直径+并查集】 codeforces 455C - Civilization
- Codeforces 455C. Civilization (树的直径+并查集)
- codeforces 455C C. Civilization(树形dp+树的直径+并查集)
- 【打CF,学算法——四星级】CodeForces 455C Civilization (【详解】并查集+树的直径)
- Codeforces 455C Civilization(并查集+树形dp)
- Codeforces 455E Civilization【思维+树的直径+并查集】
- 【CodeForces】445C Civilization 并查集
- Codeforces 455C Civilization(并查集+dfs)
- Codeforces 455C Civilization(并查集+dfs)
- codeforces round260 div1C&div2E Civilization 并查集+树的直径
- codeforces 455C Civilization 树的最长链+并查集
- Codeforces 455C —— Civilization(并查集,树上最长链)
- codeforces 466C Civilization 并查集+dfs
- Codeforces Round #260 (Div. 1)C题(并查集+树的直径)
- CF455C Civilization (并查集)
- codeforces 455C Civilization
- Android屏幕适配全攻略(最权威的官方适配指导)
- Android 面试那些事儿
- CSU-1083 2016(暴力)(湖南省十二届大学生程序设计大赛)
- 线段树从零开始
- centos6.3(final) 编译安装php5.6
- CodeForces 455C Civilization(并查集+树直径)
- 图解 Android 事件分发机制
- Servlet学习笔记---上传各种文件
- 多态中对成员的调用
- 数据仓库02
- 关于servlet destroy() 方法的小误区
- android app 知识点总结
- L脚本语言编程实例
- 【在线笔试题解题报告系列】hihocoder #1368 积水的城市2