51 nod 1427 文明 (并查集 + 树的直径)
1427 文明
题目来源: CodeForces
安德鲁在玩一个叫“文明”的游戏。大妈正在帮助他。
这个游戏里面有n个城市和m条双向的道路。城市从1到n编号。对于每一对城市,他们之间要么有唯一的一条道路,要么就是不可互达。一条道路的定义是一个包含不同城市的序列 v1, v2,...,vk , vi 和 vi+1 (1≤ i < k)之间有直接的一条道路相连。这条道路的长度是k-1。两个城市在同一区域的条件是当且仅当他们之间可以互达。
在游戏过程中,会有两个事件。
1. 安德鲁问大妈,城市x所在的区域里面最长的道路是多长。
2. 安德鲁要求大妈,合并城市x和城市y所在的区域。如果这两个城市本来在同一个区域,那么就不用合并。否则合并两个区域:从城市x所在区域选一个城市,再从城市y所在区域选一个城市,然后给这两个城市连一条边。选择这两个城市的时候要使得合并之后的区域里面最长道路尽可能小。如果有多种方案,任选一种即可。
大妈发现这些问题好难哦,所以他想请你来帮助一下。
单组测试数据。 第一行包含三个整数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可能是一样的。
对于第1类查询,输出当前区域的最长路径长度。
6 0 7 2 1 2 2 3 4 2 5 6 2 3 2 2 5 3 1 1 1 1
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;
}
转载于:https://www.cnblogs.com/Przz/p/5913697.html
51 nod 1427 文明 (并查集 + 树的直径)相关推荐
- [BZOJ 3211]花神游历各国(并查集+树状数组)
Description Solution 树状数组单点修改区间查询 我们知道一个数n最多修改loglogn次就会变为1 并查集维护每个数右边第一个不为1的位置 #include<cstdio&g ...
- P4145-上帝造题的七分钟2/花神游历各国【并查集,树状数组】
正题 题目链接:https://www.luogu.com.cn/problem/P4145 题目大意 一个序列要求支持 区间开根向下取整 区间求和 解题思路 一个数开根约logloglog次就会到1 ...
- JS 数据结构之旅 :通过JS实现栈、队列、二叉树、二分搜索树、AVL树、Trie树、并查集树、堆
JS 数据结构之旅 栈 概念 栈是一个线性结构,在计算机中是一个相当常见的数据结构. 栈的特点是只能在某一端添加或删除数据,遵循先进后出的原则 实现 每种数据结构都可以用很多种方式来实现,其实可以把栈 ...
- hdu4514 并查集+树直径
这道题题目就是说给你一个图,然后判断能不能成环,不能成环就输出最长的那一条路. 首先分析问题.怎么判断环?这是图中一个很常见的问题,在无向图中判环我们可以用并查集,在有向图中可以使用tarjan或者拓 ...
- 2017年河北省大学生程序设计竞赛 奇异旅馆 【并查集+树状数组】
奇异旅馆 Time Limit : 3000/1000ms (Java/Other) MemoryLimit : 65535/32768K (Java/Other) Total Submissio ...
- Claris’ Contest # 2 Day 2 Problem C. Dash Speed(分治+可持久化并查集+树剖)
题面 题解 \(std\)爆栈了→_→ 我们先考虑一个简化的问题,如果只有加边的情况下如何动态维护直径 合并两棵树时,设\(a,b\)为\(A\)的直径的两个端点,\(c,d\)为\(B\)的直径的两 ...
- HDU 1325POJ 1308 Is it A tree ? [并查集+树判定]
题目链接 poj hdu Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/ ...
- 路径空间HDOJ 4514 - 湫湫系列故事——设计风景线 并查集+树型DP
最近研究路径空间,稍微总结一下,以后继续补充: 题意有没说楚清的...两点间最多一条路径.... 先用并查集检查无向图否是有环... 若干个无环的无向图就是一丛林了... 那么目题转化为在一棵树上找最 ...
- 花神游历各国 题解(小清新线段树/树状数组+并查集)
题面 众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于 ...
最新文章
- 网络名称空间 实例研究 veth处于不同网络的路由问题
- ES6常用知识点概述
- 链路两段不同网段怎么通信_为什么不同网段不能通信(转)
- ubuntu中使用usb转串口
- C# 连接 Sqlserver2005 Analysis Service的总结
- SAP License:ERP顾问们,为何你会面试失败?
- Tensorflow(r1.4)API--tf.nn.max_pool
- 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.6.6版)
- 移植 libuv 到 Visual C++ 6.0 并支持在 Windows XP 系统下编译
- kettle日志解析_Kettle日志-基础篇
- 运营主管的OKR案例
- lzg_ad: SQL SERVER2000安装问题
- js中math常用使用方法
- 转载:联想小新进入BIOS方法
- 统计员工信息c语言设计,工资信息管理系统C语言设计
- VINS的理解(I-V)
- QQ空间触屏登录加密JS
- it Ebook 免费
- 【愚公系列】2022年09月 微信小程序-WebGL画渐变色正方形
- 王怀南:从谷歌之父到育儿专家