题目链接:

题目

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. AngularJS 整理资料

    AngularJS是Google开源的一款JavaScript MVC框架,弥补了HTML在构建应用方面的不足,其通过使用指令(directives)结构来扩展HTML词汇,使开发者可以使用HTML来 ...

  2. java演示facade(外观)模式

    实际应用中,原来的代码涉及多个子系统时,重新进行类的设计,将原来分散在源码中的类结构及方法重新组合,形成新的.统一的接口,供上层应用使用. Facade所面对的往往是多个类或其它程序单元,通过重新组合 ...

  3. Linux 命令 - wc: 统计文件的行数、字数和字节数

    命令格式 wc [OPTION]... [FILE]... 命令格式 -c, --bytes 打印字节数. -m, --chars 打印字符数. -l, --lines 打印行数. -L, --max ...

  4. sql中的case when语句

    1.在where子句中: CREATE TABLE `hello`.`sometbl` ( `id` INT NOT NULL AUTO_INCREMENT , `a` VARCHAR(45) NUL ...

  5. HDOJ2026首字母变大写

    首字母变大写 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. SSIS_TXT有规则资料导入到EXCEL

    SSIS开发需要完全安装sqlserver.本次demo是sqlserver2008. 1.创建项目 2.解决方案打开如图所示. 3.拉取一个序列容器,一个数据流任务. 4.在数据流任务点击.拉取一个 ...

  7. <转载>提升程序的特权(AdjustTokenPrivileges)

    首先列出需要的函数 1.OpenProcessToken 2.AdjustTokenPrivileges 3. LookupPrivilegeValue ----------------------- ...

  8. 合理使用mysql中的load data infile导入数据

    基本语法: load data  [low_priority] [local] infile 'file_name txt' [replace | ignore]into table tbl_name ...

  9. Android系统中提供的原子操作

    代码的实现位于文件system/core/include/cutils中 http://androidxref.com/4.4.3_r1.1/xref/system/core/include/cuti ...

  10. Tomcat上配置连接池{ connect error=Name [jdbc/OracleDB] is not bound in this Context. Unable to find [jdbc]}

    . 在学习期间,从未实践过在tomcat上配置连接池,今天终于实现一次,在tomcat玩了一把,不知道你是否现在有和我一样的困境.废话少说直接上代码   java  public static Con ...