题目链接:

题目

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 树的中心+并查集的更多相关文章

  1. Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径

    C. Civilization Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/probl ...

  2. 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 ...

  3. 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/ ...

  4. 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 ...

  5. Codeforces Round #329 (Div. 2) D. Happy Tree Party(LCA+并查集)

    题目链接 题意:就是给你一颗这样的树,用一个$y$来除以两点之间每条边的权值,比如$3->7$,问最后的y的是多少,修改操作是把权值变成更小的. 这个$(y<=10^{18})$除的权值如 ...

  6. 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. ...

  7. 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 ...

  8. Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)

    题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂  总共有m对试剂能反应,按不同的 ...

  9. 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 ...

随机推荐

  1. MyBatis(3.2.3) - Paginated ResultSets using RowBounds

    Sometimes, we may need to work with huge volumes of data, such as with tables with millions of recor ...

  2. winform 渐变(非API)

    public FrmMain() { InitializeComponent(); //窗体显示特效 Opacity = 0.0; //窗体透明度为0 fadeTimer.Start(); //计时开 ...

  3. html5 canvas 圆形抽奖的实例

    年底没啥,抽空学习了canvas,写了个html5抽奖的代码,造了个轮子,有用的童鞋可以拿走. 其中,canvas.onclick触发抽奖行为,概率可以在core.lottery()函数上添加,美化也 ...

  4. OC3_Copy及MultableCopy

    // // main.m // OC3_Copy及MultableCopy // // Created by zhangxueming on 15/6/19. // Copyright (c) 201 ...

  5. c#基础笔记-----------集合

    首先所谓集合是用于管理对象的容器类.一方面集合将独立的对象汇集成群集,作为一个群集来管理,以便进行整体性操作:而另一方面,集合可以方便地获取群集中的个体,进行个体化操作.在.Net中,集合被封装为对象 ...

  6. nginx上传文件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. linux端口与进程命令

    1 lsof命令 lsof -i:portNum 查出来与该端口相关的所有程序 2 netstat命令: netstat -lnp

  8. 引用、return

    C语言中没有引用,引用(reference)是c++对c语言的重要扩充.通俗点说,引用就是“起别名”.比如变量data,和它的引用 RefData.虽然名字不同,但是操作他们的时候,都操作的是相同的内 ...

  9. 《SELinux安全上下文的管理(含图)》RedHat6.3——步骤详细、条理清晰

    1.为什么浏览器只识别/var/www/html下的文件? 2.为什么不识别别的目录下的index.html文件呢? 3.这里牵扯到身份证,先安装软件包. 4.打开selinux 5.建立一个新的目录 ...

  10. 按照自己的理解实现比特交换协议(alternating-bit protocol)

    一开始的思路是想写两个程序的,发送端和接收端.但是后来想了下,因为是模拟的,所以不用这么麻烦,直接自己定制场景(比如说丢包阿,包出错阿,超时之类的). 基本上是根据上图所写的,一个函数发包,一个函数接 ...