题目链接:

题目

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. Redis 命令 - Transactions

    DISCARD Discard all commands issued after MULTI 127.0.0.1:6379> MGET bank:A:account bank:B:accoun ...

  2. jQuery概述,代码举例及最新版下载

    jQuery是一个快速的,小巧的,具有强大功能的JavaScript库. 它的基本功能包括: 1)访问和操作DOM元素 2)控制页面样式(可以兼容各种浏览器) 3)对页面事件的处理 4)大量插件在页面 ...

  3. Android从imageview中获得bitmap

    第一种: 使用setDrawingCacheEnabled()和getDrawingCache()这两种方法,第一个是为了设置是否开启缓存,第二个就可以直接获得imageview中的缓存,一般来说需要 ...

  4. ubuntu 更新软件源

    ubuntu 更新软件源 修改文件sources.list 位于/etc/apt/sources.list,并备份原文件为sources.list.bak deb http://mirrors.163 ...

  5. CentOS 关闭蜂鸣

    临时:sudo rmmod pcspkr 永久 /etc/inputrc文件中把 set bell-style none 前的注释去掉,改为 set bell-style off 转自:http:// ...

  6. 第一个Apple Watch小例子

    原文在这, 不过他说的add target按照他的说法还真没找到(估计是我的眼瞎了或者是版本不一样),还有就是好记性不如烂博客,先自己能看懂就行了. 请用Single View Application ...

  7. asp.net 文件操作小例子(创建文件夹,读,写,删)

      静态生成要在虚拟目录下创建文件夹 来保存生成的页面 那么就要对文件进行操作 一.创建文件夹 using System.IO; string name = "aa"; strin ...

  8. CSS 初体验之一

    层叠样式表 (Cascading Style Sheets)”,它主要是用于定义HTML内容在浏览器内的显示样式. 1.首先先看盒装模型,如下图,平时设置的width,height是指元素内容(con ...

  9. C++对象的JSON序列化与反序列化探索

    一:背景 作为一名C++开发人员,我一直很期待能够像C#与JAVA那样,可以轻松的进行对象的序列化与反序列化,但到目前为止,尚未找到相对完美的解决方案. 本文旨在抛砖引玉,期待有更好的解决方案:同时向 ...

  10. Qt5.4生成安装包过程

    所需工具: 1.  HM NIS Edit 2.  windeployqt.exe 第一个工具需要自己去网上下载,第二个工具可以在qt安装目录下找到:D:\qtopengl\5.4\mingw491_ ...