CodeForces - 455C Civilization (dfs+并查集)
http://codeforces.com/problemset/problem/455/C
题意
n个结点的森林,初始有m条边,现在有两种操作,1.查询x所在联通块的最长路径并输出;2.将结点x和y所在的块连在一起,并使新块的最长路径最短。
分析
先想想最长路径怎么求,倘若我们以一个点为根,那么最长路径就是这棵有根树的直径了,那么我们可以先从任意点u出发,走到最远点v,再从v出发走到最远点,此时就能得出这棵树的直径了。现在想想怎么把两块合并?应该想到的是并查集,由于还得考虑合并后的直径最小,经过推理,由这两棵树的重心合并是最优的,也就是(d+1)/2的位置,由于两个重心连接会产生一条新边,所以+1。
- #include<iostream>
- #include<cmath>
- #include<cstring>
- #include<queue>
- #include<vector>
- #include<cstdio>
- #include<algorithm>
- #include<map>
- #include<set>
- #define rep(i,e) for(int i=0;i<(e);i++)
- #define rep1(i,e) for(int i=1;i<=(e);i++)
- #define repx(i,x,e) for(int i=(x);i<=(e);i++)
- #define X first
- #define Y second
- #define PB push_back
- #define MP make_pair
- #define mset(var,val) memset(var,val,sizeof(var))
- #define scd(a) scanf("%d",&a)
- #define scdd(a,b) scanf("%d%d",&a,&b)
- #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
- #define pd(a) printf("%d\n",a)
- #define scl(a) scanf("%lld",&a)
- #define scll(a,b) scanf("%lld%lld",&a,&b)
- #define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
- #define IOS ios::sync_with_stdio(false);cin.tie(0)
- using namespace std;
- typedef long long ll;
- template <class T>
- void test(T a){cout<<a<<endl;}
- template <class T,class T2>
- void test(T a,T2 b){cout<<a<<" "<<b<<endl;}
- template <class T,class T2,class T3>
- void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;}
- const int inf = 0x3f3f3f3f;
- const ll INF = 0x3f3f3f3f3f3f3f3fll;
- const ll mod = 1e9+;
- int T;
- void testcase(){
- printf("Case %d: ",++T);
- }
- const int MAXN = 3e5+;
- const int MAXM = ;
- int n,m,Q,root,ans,tot,rec;
- int fa[MAXN],num[MAXN],head[MAXN];
- struct node{
- int to,nxt;
- }e[MAXN<<];
- void addEdge(int u,int v){
- e[tot].to=v;
- e[tot].nxt=head[u];
- head[u]=tot++;
- }
- int Find(int x){
- return fa[x]==x?x:fa[x]=Find(fa[x]);
- }
- void Union(int a,int b){
- int xa=Find(a);
- int xb=Find(b);
- if(xa!=xb){
- if(num[xa]<num[xb]) swap(xa,xb);
- num[xa]=max(num[xa],(num[xa]+)/+(num[xb]+)/+);
- fa[xb]=xa;
- }
- }
- void dfs(int u,int p,int d){
- fa[u]=root;
- if(d>ans){
- ans=d;
- rec=u;
- }
- for(int i=head[u];~i;i=e[i].nxt){
- int v=e[i].to;
- if(v!=p) dfs(v,u,d+);
- }
- }
- void init(){
- tot=;
- mset(head,-);
- mset(num,);
- for(int i=;i<=n;i++) fa[i]=i;
- }
- int main() {
- #ifdef LOCAL
- freopen("in.txt","r",stdin);
- #endif // LOCAL
- int a,b;
- scddd(n,m,Q);
- init();
- for(int i=;i<m;i++){
- scdd(a,b);
- addEdge(a,b);
- addEdge(b,a);
- }
- for(int i=;i<=n;i++){
- if(fa[i]==i){
- root=rec=i;
- ans=-;
- dfs(i,,);
- ans=-;
- dfs(rec,,);
- num[i]=ans;
- }
- }
- while(Q--){
- scd(a);
- if(a==){
- scd(b);
- printf("%d\n",num[Find(b)]);
- }else{
- scdd(a,b);
- Union(a,b);
- }
- }
- return ;
- }
CodeForces - 455C Civilization (dfs+并查集)的更多相关文章
- CodeForces 455C Civilization (并查集+树的直径)
Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...
- CodeForces 455C Civilization(并查集+树直径)
好久没有写过图论的东西了,居然双向边要开两倍空间都忘了,不过数组越界cf居然给我报MLE??这个题题意特别纠结,一开始一直不懂添加的边长是多长... 题意:给你一些点,然后给一些边,注意没有重边 环, ...
- Codeforces 455C Civilization(并查集+dfs)
题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...
- DFS/并查集 Codeforces Round #286 (Div. 2) B - Mr. Kitayuta's Colorful Graph
题目传送门 /* 题意:两点之间有不同颜色的线连通,问两点间单一颜色连通的路径有几条 DFS:暴力每个颜色,以u走到v为结束标志,累加条数 注意:无向图 */ #include <cstdio& ...
- codeforces 456 E. Civilization(并查集+数的直径)
题目链接:http://codeforces.com/contest/456/problem/E 题意:给出N个点,M条边,组成无环图(树),给出Q个操作,操作有两种: 1 x,输出x所在的联通块的最 ...
- Codeforces 571D - Campus(并查集+线段树+DFS 序,hot tea)
Codeforces 题目传送门 & 洛谷题目传送门 看到集合的合并,可以本能地想到并查集. 不过这题的操作与传统意义上的并查集不太一样,传统意义上的并查集一般是用来判断连通性的,而此题还需支 ...
- Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)
<题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...
- CF455C Civilization (并查集)
CF456E Codeforces Round #260 (Div. 1) C Codeforces Round #260 (Div. 2) E http://codeforces.com/conte ...
- Codeforces Gym 100463E Spies 并查集
Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...
随机推荐
- Win10 1803 升级之后无法使用 共享目录的解决方法
1. 自己的虚拟机升级了win10 最新版本 1803 但是发现 使用共享文件夹时报错: 2, 百度发现解决方案还是非常简单的. 需要安装一个 功能 3.方法: 开始 运行 输入 control 打开 ...
- pandas分组group
Pandas对象可以分成任何对象.有多种方式来拆分对象,如 - obj.groupby(‘key’) obj.groupby([‘key1’,’key2’]) obj.groupby(key,axis ...
- panda迭代
1.注意 - 不要尝试在迭代时修改任何对象.迭代是用于读取,迭代器返回原始对象(视图)的副本,因此更改将不会反映在原始对象上. 2.itertuples()方法将为DataFrame中的每一行返回一个 ...
- SpringBoot(十七)_springboot跨域处理
本文转自:Vi的技术博客 什么是跨域 首先,我们需要了解一下一个URL是怎么组成的: // 协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址 http: + // + www.baidu ...
- BZOJ2819Nim——树链剖分+线段树+Nim游戏
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- ansible创建vmware虚拟机
环境:vmware 虚拟化需求:如果业务部门一次提几十台甚至几百台虚拟机需求,一个个的手动创建肯定耗时 使用ansible vmware_guest 创建虚拟机,避免手动一台一台创建的纯手工 工作废话 ...
- DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
前缀和优化 当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下.运算一般都要满足可减性. 比较naive就不展开了. 题目 [Todo]洛谷P2513 [HAOI2009]逆序对数列 [D ...
- adb is down 的解决方法
今天装完android Eclipse 之后 ,运行时报出这么个错误 : The connection to adb is down, and a severe error has occured. ...
- Raspbian首次安装后无法使用SSH链接
使用Putty连接树莓派,出现Network Error:Connection Refused 新版的Raspbian系统默认禁用了SSH. 解决方法:在/boot分区创建名为"ssh&qu ...
- 2019.3.18考试&2019.3.19考试&2019.3.21考试
2019.3.18 C O D E T1 树上直接贪心,环上for一遍贪心 哇说的简单,码了将近一下午终于码出来了 感觉自己码力/写题策略太糟糕了,先是搞了一个细节太多的写法最后不得不弃疗了,然后第二 ...