51 nod 1427 文明 (并查集 + 树的直径)

时间:2023-02-25 17:21:19

1427 文明51 nod 1427 文明 (并查集 + 树的直径)

题目来源: CodeForces

基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
 

安德鲁在玩一个叫“文明”的游戏。大妈正在帮助他。

这个游戏里面有n个城市和m条双向的道路。城市从1到n编号。对于每一对城市,他们之间要么有唯一的一条道路,要么就是不可互达。一条道路的定义是一个包含不同城市的序列 v1, v2,...,vk ,  vi  和  vi+1 (1≤ i < k)之间有直接的一条道路相连。这条道路的长度是k-1。两个城市在同一区域的条件是当且仅当他们之间可以互达。

在游戏过程中,会有两个事件。

1.    安德鲁问大妈,城市x所在的区域里面最长的道路是多长。

2.    安德鲁要求大妈,合并城市x和城市y所在的区域。如果这两个城市本来在同一个区域,那么就不用合并。否则合并两个区域:从城市x所在区域选一个城市,再从城市y所在区域选一个城市,然后给这两个城市连一条边。选择这两个城市的时候要使得合并之后的区域里面最长道路尽可能小。如果有多种方案,任选一种即可。

大妈发现这些问题好难哦,所以他想请你来帮助一下。

Input
单组测试数据。
第一行包含三个整数n,m,q(1 ≤ n ≤ 3*10^5; 0 ≤ m < n; 1 ≤ q ≤ 3*10^5),分别表示城市数目,道路数目,查询数目。
接下来m行,每行有两个整数 ai 和bi (ai ≠ bi; 1 ≤ ai, bi ≤ n)。表示ai和bi之间有一条直接相连的道路。两个城市之间最多有一条直接相连的道路。
接下来q行的格式是下列之一:
1 xi 。(1 ≤ xi ≤ n)。这种情况要查询当前xi所在的区域的最长道路。
2 xi yi。 (1 ≤ xi, yi ≤ n)。这种情况下要求合并xi和yi所在的区域。注意:xi和yi可能是一样的。
Output
对于第1类查询,输出当前区域的最长路径长度。
Input示例
6 0 7
2 1 2
2 3 4
2 5 6
2 3 2
2 5 3
1 1
1 1
Output示例
4
4
/*
51 nod 1427 文明 (并查集 + 树的直径) problem:
给你n个城市,m条双向边连接,然后是q个查询
1 x: 城市x所在的区域的最长道路
2 x y:将两个城市的所在区域连接,要求维护最长路最短. solve:
一个区域的最长路就相当于树的直径.因为两个城市之间最多只有一条路径.
合并的话,如果要求最短,那么相当于将两条直径的中点相连. 所以已知A,B的直径可计算出新的直径的值
(注意还要与A,B的直径进行下比较).
先处理出每个区域的树的直径.然后可给每个区域打上标记,用并查集合并维护一下区域的树的直径. hhh-2016/09/27-17:21:09
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <math.h>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 3e5 + 100;
const int inf = 0x3f3f3f3f;
const ll mod = 1000000007;
const double eps = 1e-7;
template<class T> void read(T&num)
{
char CH;
bool F=false;
for(CH=getchar(); CH<'0'||CH>'9'; F= CH=='-',CH=getchar());
for(num=0; CH>='0'&&CH<='9'; num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
if(!p)
{
puts("0");
return;
}
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} struct node
{
int v,next;
} edge[maxn << 1];
ll Max;
int tot,pos;
int head[maxn];
int vis[maxn];
//int ans[i];
int pre[maxn];
struct Node
{
ll dis;
int pre;
} pnode[maxn];
void init(int n)
{
memset(head,-1,sizeof(head));
tot = 0;
for(int i = 1; i <= n; i++)
{
vis[i] = 0;
pnode[i].pre = i;
pnode[i].dis = 1;
}
}
void add_edge(int u,int v)
{
edge[tot].v = v,edge[tot].next = head[u],head[u] = tot ++;
} void dfs(int u,int fa,ll len,int anc)
{
vis[u] = 1;
pnode[u].pre = anc;
if(len > Max)
{
Max = len;
pos = u;
} for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if(v == fa)
continue;
dfs(v,u,len + 1LL,anc);
}
} void cal(int now)
{
int from;
pos = 0,Max =0 ;
dfs(now,-1,0,now);
from = pos;
pos = 0,Max = 0;
dfs(from,-1,0,now);
pnode[now].dis = Max;
} int fin(int u)
{
if(pnode[u].pre != u)
return pnode[u].pre = fin(pnode[u].pre);
return u;
} void unio(int u,int v)
{
int ta = fin(u);
int tb = fin(v); if(ta == tb)
return ;
if(ta > tb)
swap(ta,tb);
pnode[ta].pre =tb;
ll tMax = 0;
tMax = max(pnode[ta].dis,pnode[tb].dis);
tMax = max(tMax,(pnode[ta].dis+1LL)/2LL+(pnode[tb].dis + 1LL)/2LL + 1LL);
pnode[tb].dis = tMax;
pnode[ta].dis= tMax;
} int main()
{
int n,m,q;
int u,v,ob;
read(n),read(m),read(q);
init(n);
for(int i = 1; i <= m; i++)
{
read(u),read(v);
add_edge(u,v);
add_edge(v,u);
}
for(int i = 1;i <= n;i++)
{
if(!vis[i])
cal(i);
}
for(int i = 1; i <= q; i++)
{
read(ob);
if(ob == 1)
{
read(u);
int ta = fin(u);
print(pnode[ta].dis);
}
else
{
read(u),read(v);
unio(u,v);
}
}
return 0;
}

  

51 nod 1427 文明 (并查集 + 树的直径)的更多相关文章

  1. 51 nod 1515 明辨是非&lpar;并查集合并&rpar;

    1515 明辨是非题目来源: 原创基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以 ...

  2. 【bzoj3362&sol;3363&sol;3364&sol;3365】&lbrack;Usaco2004 Feb&rsqb;树上问题杂烩 并查集&sol;树的直径&sol;LCA&sol;树的点分治

    题目描述 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样, 图中农场用F ...

  3. CodeForces 455C Civilization (并查集&plus;树的直径)

    Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...

  4. 洛谷P4092 &lbrack;HEOI2016&sol;TJOI2016&rsqb;树 并查集&sol;树链剖分&plus;线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  5. BZOJ-3211花神游历各国 并查集&plus;树状数组

    一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...

  6. BZOJ3211 花神游历各国 并查集 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3211 题意概括 有n个数形成一个序列. m次操作. 有两种,分别是: 1. 区间开根(取整) 2. ...

  7. hdu 6200 mustedge mustedge&lpar;并查集&plus;树状数组 或者 LCT 缩点&rpar;

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  8. 【bzoj4869】&lbrack;Shoi2017&rsqb;相逢是问候 扩展欧拉定理&plus;并查集&plus;树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

  9. 并查集&plus;树链剖分&plus;线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...

随机推荐

  1. &lbrack;LeetCode&rsqb; Multiply Strings 字符串相乘

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  2. java集合练习——Bank

    练习:用List表示多重性 练习目标-在类中使用List作为模拟集合操作: 在本练习中,将用List实现银行与客户间的多重关系. 任务:对银行来说,可添加Bank类. Bank 对象跟踪自身与其客户间 ...

  3. 堆排序(C&plus;&plus;版)

    #include <iostream> using namespace std; void HeapAdjust(int* a, int start, int n) { int max=s ...

  4. ural 1018 Binary Apple Tree(树形dp &vert; 经典)

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

  5. IOS系统对fixed定位支持不好的解决方法

    问题: IOS 中所有浏览器,当页面上的输入框获得焦点时,呼出键盘. 页面底部的导航栏(position:fixed)会被键盘顶到页面的中间. 而当输入框失去焦点时,导航栏停留在页面中间,造成页面错乱 ...

  6. POJ-2632 Crashing Robots模拟

    题目链接: https://vjudge.net/problem/POJ-2632 题目大意: 在一个a×b的仓库里有n个机器人,编号为1到n.现在给出每一个机器人的坐标和它所面朝的方向,以及m条指令 ...

  7. Video clip 视频剪辑:入门级

    作为一个对小说漫画电视剧电影的设计有着自己独特需求的人,一直对视频剪辑有着浓厚的兴趣,之前用爱剪辑这种通俗易上手的软件做过简单的小视频.但是这个毕竟满足不了我自己的需求而且属于完全门外汉级别.这次终于 ...

  8. 四种途径提高RabbitMQ传输数据的可靠性(二)

    前言 上一篇四种途径提高RabbitMQ传输消息数据的可靠性(一)已经介绍了两种方式提高数据可靠性传输的方法,本篇针对上一篇中提出的问题(1)与问题(2)提出解决常用的方法. 本文其实也就是结合以上四 ...

  9. es6(二)

    三 . 正则扩展: 1.构造函数的扩展 let regex = new Regex('xyz','i'); let regex2 = new Regex(/xyz/i);//test() 方法用于检测 ...

  10. DevExpress 只允许修改指定列

    gridView1.OptionsBehavior.Editable = true; gridView1.OptionsBehavior.ReadOnly = false; foreach (Grid ...