Codeforces Round #260 (Div. 1) C. Civilization 树的中心+并查集
题目链接:
题目
C. Civilization
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
问题描述
Andrew plays a game called "Civilization". Dima helps him.
The game has n cities and m bidirectional roads. The cities are numbered from 1 to n. Between any pair of cities there either is a single (unique) path, or there is no path at all. A path is such a sequence of distinct cities v1, v2, ..., vk, that there is a road between any contiguous cities vi and vi + 1 (1 ≤ i < k). The length of the described path equals to (k - 1). We assume that two cities lie in the same region if and only if, there is a path connecting these two cities.
During the game events of two types take place:
Andrew asks Dima about the length of the longest path in the region where city x lies.
Andrew asks Dima to merge the region where city x lies with the region where city y lies. If the cities lie in the same region, then no merging is needed. Otherwise, you need to merge the regions as follows: choose a city from the first region, a city from the second region and connect them by a road so as to minimize the length of the longest path in the resulting region. If there are multiple ways to do so, you are allowed to choose any of them.
Dima finds it hard to execute Andrew's queries, so he asks you to help him. Help Dima.
输入
The first line contains three integers n, m, q (1 ≤ n ≤ 3·105; 0 ≤ m < n; 1 ≤ q ≤ 3·105) — the number of cities, the number of the roads we already have and the number of queries, correspondingly.
Each of the following m lines contains two integers, ai and bi (ai ≠ bi; 1 ≤ ai, bi ≤ n). These numbers represent the road between cities ai and bi. There can be at most one road between two cities.
Each of the following q lines contains one of the two events in the following format:
1 xi. It is the request Andrew gives to Dima to find the length of the maximum path in the region that contains city xi (1 ≤ xi ≤ n).
2 xi yi. It is the request Andrew gives to Dima to merge the region that contains city xi and the region that contains city yi (1 ≤ xi, yi ≤ n). Note, that xi can be equal to yi.
输出
For each event of the first type print the answer on a separate line.
样例
input
6 0 6
2 1 2
2 3 4
2 5 6
2 3 2
2 5 3
1 1
output
4
题意
给你一个森林,进行两个操作:
- 输入一个x,求x所在的树的直径
- 输入u,v,把u,v所在的树合并起来
题解
求出每颗树的中心,作为集合的中心。
两颗树合并,只要把直径比较短的树的中心合并到直径比较长的树的中心就可以了。
合并完之后的直径长度为max(r1,r2,(r1+1)/2+(r2+1)/2+1)。其中r1为第一颗树的直径,r2为第二颗树的直径
没写过树的中心,写搓了:
先求树的直径,然后找直径的中间点。连续dfs了三次。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 3e5+10;
int n, m, q;
int fa[maxn],r[maxn];
int find(int x) {
return fa[x] = fa[x] == x ? x : find(fa[x]);
}
vector<int> G[maxn];
int vis[maxn];
void dfs(int u, int p, int &len, int &x,int d) {
if (len < d) x = u, len = d;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v == p) continue;
dfs(v, u, len, x, d + 1);
}
}
bool dfs2(int u, int p, int y, int len,int dep,int &ctr) {
bool ok = 0;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v == p) continue;
ok=dfs2(v, u, y, len,dep+1, ctr);
if (ok&&dep == len / 2) ctr = u;
if (ok) return ok;
}
if (u == y) ok = 1;
return ok;
}
void dfs3(int u, int p,int ctr) {
vis[u] = 1;
fa[u] = ctr;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v == p) continue;
dfs3(v, u, ctr);
}
}
void init() {
for (int i = 0; i <= n; i++) fa[i] = i,r[i]=0;
memset(vis, 0, sizeof(vis));
}
int main() {
scanf("%d%d%d", &n, &m, &q);
init();
int cmd, u,v,x;
while (m--) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
int ctr, l, x, y;
l = -1; dfs(i, -1, l, x, 0);
l = -1; dfs(x, -1, l, y, 0);
ctr = i;
dfs2(x, -1, y, l,0,ctr);
r[ctr] = l;
dfs3(i, -1,ctr);
}
}
while (q--) {
scanf("%d", &cmd);
if (cmd == 1) {
scanf("%d", &x);
int px = find(x);
printf("%d\n", r[px]);
}
else {
scanf("%d%d", &u, &v);
int pu = find(u), pv = find(v);
if (pu != pv) {
int maxr = max(r[pu], r[pv]);
maxr = max(maxr, (r[pu] + 1) / 2 + (r[pv] + 1) / 2 + 1);
if (r[pu] > r[pv]) fa[pv] = pu, r[pu] = maxr;
else fa[pu] = pv, r[pv] = maxr;
}
}
}
return 0;
}
发现只要求直径就可以了,随便找个点为根,不用找树中心。。orz。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 3e5+10;
int n, m, q;
int fa[maxn],r[maxn];
int find(int x) {
return fa[x] = fa[x] == x ? x : find(fa[x]);
}
vector<int> G[maxn];
int rt;
void dfs(int u, int p, int &len, int &x,int d) {
fa[u] = rt;
if (len < d) x = u, len = d;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v == p) continue;
dfs(v, u, len, x, d + 1);
}
}
void init() {
for (int i = 0; i <= n; i++) fa[i] = i,r[i]=0;
}
int main() {
scanf("%d%d%d", &n, &m, &q);
init();
int cmd, u,v,x;
while (m--) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for (int i = 1; i <= n; i++) {
if (fa[i]==i) {
int l, x, y;
rt = i;
l = -1; dfs(i, -1, l, x, 0);
l = -1; dfs(x, -1, l, y, 0);
r[i] = l;
}
}
while (q--) {
scanf("%d", &cmd);
if (cmd == 1) {
scanf("%d", &x);
int px = find(x);
printf("%d\n", r[px]);
}
else {
scanf("%d%d", &u, &v);
int pu = find(u), pv = find(v);
if (pu != pv) {
int maxr = max(r[pu], r[pv]);
maxr = max(maxr, (r[pu] + 1) / 2 + (r[pv] + 1) / 2 + 1);
if (r[pu] > r[pv]) fa[pv] = pu, r[pu] = maxr;
else fa[pu] = pv, r[pv] = maxr;
}
}
}
return 0;
}
Codeforces Round #260 (Div. 1) C. Civilization 树的中心+并查集的更多相关文章
- Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径
C. Civilization Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/probl ...
- Codeforces Round #396 (Div. 2) D. Mahmoud and a Dictionary 并查集
D. Mahmoud and a Dictionary 题目连接: http://codeforces.com/contest/766/problem/D Description Mahmoud wa ...
- Codeforces Round #250 (Div. 1) B. The Child and Zoo 并查集
B. The Child and Zoo Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/438/ ...
- Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 暴力并查集
D. Dividing Kingdom II 题目连接: http://www.codeforces.com/contest/687/problem/D Description Long time a ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party(LCA+并查集)
题目链接 题意:就是给你一颗这样的树,用一个$y$来除以两点之间每条边的权值,比如$3->7$,问最后的y的是多少,修改操作是把权值变成更小的. 这个$(y<=10^{18})$除的权值如 ...
- Codeforces Round #212 (Div. 2) D. Fools and Foolproof Roads 并查集+优先队列
D. Fools and Foolproof Roads You must have heard all about the Foolland on your Geography lessons. ...
- Codeforces Round #376 (Div. 2) A B C 水 模拟 并查集
A. Night at the Museum time limit per test 1 second memory limit per test 256 megabytes input standa ...
- Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)
题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂 总共有m对试剂能反应,按不同的 ...
- Codeforces Round #385 (Div. 2)A B C 模拟 水 并查集
A. Hongcow Learns the Cyclic Shift time limit per test 2 seconds memory limit per test 256 megabytes ...
随机推荐
- ORA-01790 错误处理
今天在练手的时候出现了一个ORA-01790 的错误,决定把他写下来保留起来. 先来创建两张测试用的简单的表. SQL> create table test01 (id number(3),na ...
- oracle的nvl和sql server的isnull
最近公司在做Oracle数据库相关产品,在这里作以小结: ISNULL()函数 语法 ISNULL ( check_expression , replacement_value) 参数 c ...
- Spring(3.2.3) - Beans(1): Spring 容器
BeanFactory & ApplicationContext org.springframework.beans.factory.BeanFactory 是最基本的 Spring 容器接口 ...
- Ehcache(2.9.x) - API Developer Guide, Using Explicit Locking
About Explicit Locking Ehcache contains an implementation which provides for explicit locking, using ...
- Linux 命令 - passwd: 更改用户密码
命令格式 passwd [-k] [-l] [-u [-f]] [-d] [-e] [-n mindays] [-x maxdays] [-w warndays] [-i inactiveda ...
- Redis 命令 - Keys
DEL key [key ...] Delete a key 127.0.0.1:6379> SET foo hello OK 127.0.0.1:6379> DEL foo hello ...
- hive,spark的远程调试设置
spark的远程调试 spark-env.sh文件里面,加上下面配置即可: if [ "$DEBUG_MODE" = "true" ]; then export ...
- ASP判断当前页面上是否有参数ID传递过来
遇到了一个这样的ASP问题: 在当前页面上判断,是否有参数ID传递过来? 如果没有,显示“没有参数传递过来”. 如果有传递,但值为空,显示“存在参数,但参数为空” <% if (request( ...
- HDOJ2017字符串统计
字符串统计 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- ubuntu(16.04.01)学习-day2
1.建立硬链接: ln main.c mainsoft 2.建立软链接:ln -s main.c soft 3.对文档进行统计 wc main.c返回行.单词数和字符数 4.查看相应命令的描述 wha ...