CF456E

Codeforces Round #260 (Div. 1) C

Codeforces Round #260 (Div. 2) E

http://codeforces.com/contest/455/problem/C

C. Civilization
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard 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:

  1. Andrew asks Dima about the length of the longest path in the region where city x lies.
  2. 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.

Input

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

For each event of the first type print the answer on a separate line.

Sample test(s)
Input
6 0 6
2 1 2
2 3 4
2 5 6
2 3 2
2 5 3
1 1
Output
4

题意:

给出N个点,M条边,组成无环图(树),给出Q个操作,操作有两种:

1 x  ,输出x所在的联通块的最长路;

2 x y  ,若x和y在同一联通块,则不操作;若不在同一联通块,则选择这两个联通块的各一个城市连一条边,使新的联通块的最长路最短,若有多种选择则随便选。

题解:

并查集+树的直径

我是看http://blog.csdn.net/keshuai19940722/article/details/38455333的碉炸题解学会的,简直碉炸。

这题认真看其实不难,只是我当时太怂了没看……

首先我们根据初始的边用求树的直径的方法求出每块的最长路,方法就是两遍dfs,第一遍找距离起点最远的点x,这个x肯定是最长路的一端,然后我们从x再dfs一遍,得到最长路md[x],顺便把整个块的father设为x。

然后操作一就很容易实现,主要是操作二。操作二其实不用真的去连那条边,只要心中有那条边就行,因为连起来后其实主要我们也只看每个块最长路md[x],其他信息都不用管。设两个块的祖先为fx,fy,设fx的最长路不小于fy的最长路,则我们要把fy的father设为fx,然后更新md[fx]。这个厉害了,我们只要一个超碉的式子就能得到新的md[fx]

    md[fx]=max(md[fx], (md[fx]+)/ + (md[fy]+)/ +  );

就是把[x块的最长路的中间点]连接[y块的最长路的中间点],得到的新路的长度是(x块最长路的一半)加上(y块最长路的一半)加上1。

怪不得天梯第一的tourist大神能十多分钟做出来,果然水,不要不服!只是我们比题还水,一下看不出来这样做…

代码:

 //#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usint unsigned int
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) printf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1biao.out","w",stdout) const int maxn=; struct EDGE{
int v,next;
}e[maxn<<];
int head[maxn],en;
int f[maxn],md[maxn];
int n,m,q;
int maxd,maxi,thefather;
void add(int x,int y){
e[en].v=y;
e[en].next=head[x];
head[x]=en++;
} int getfather(int x){
return f[x]==x ? x:f[x]=getfather(f[x]);
} void link(int x,int y){
int fx,fy;
fx=getfather(x);
fy=getfather(y);
if(fx==fy)return;
if(md[fx]<md[fy])swap(fx,fy);
md[fx]=max(md[fx], (md[fx]+)/ + (md[fy]+)/ + );
f[fy]=fx;
} void dfs(int x,int prex,int step){
f[x]=thefather;
if(step>maxd){
maxd=step;
maxi=x;
}
for(int i=head[x]; i!=-; i=e[i].next)
if(e[i].v!=prex) dfs(e[i].v,x,step+);
} void check(int a[],int n){
for(int i=;i<n;i++)
printf("%d ",a[i]);
puts("");
} int main()
{
int i,x,y,z;
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
memset(head,-,sizeof(head));
en=;
REP(i,m) {
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(i=; i<=n ;i++)
f[i]=i;
for(i=; i<=n; i++)
if(f[i]==i){
maxd=-;
thefather=i;
dfs(i,-,);
maxd=-;
thefather=maxi;
dfs(thefather,-,);
md[thefather]=maxd;
}
REP(i,q){
scanf("%d",&z);
if(z==){
scanf("%d",&x);
printf("%d\n",md[getfather(x)]);
}else{
scanf("%d%d",&x,&y);
link(x,y);
// check(md,n+1);
// check(f,n+1);
}
}
}
return ;
}

CF455C Civilization (并查集)的更多相关文章

  1. cf455C Civilization (并查集)

    并查集维护每个联通块的直径和最小的最大深度,每次连得时候连的肯定是最大深度最小的那两个点 #pragma GCC optimize(3) #include<bits/stdc++.h> # ...

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

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

  3. Codeforces 455C Civilization(并查集+dfs)

    题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...

  4. CodeForces 455C Civilization (并查集+树的直径)

    Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...

  5. CodeForces - 455C Civilization (dfs+并查集)

    http://codeforces.com/problemset/problem/455/C 题意 n个结点的森林,初始有m条边,现在有两种操作,1.查询x所在联通块的最长路径并输出:2.将结点x和y ...

  6. CodeForces 455C Civilization(并查集+树直径)

    好久没有写过图论的东西了,居然双向边要开两倍空间都忘了,不过数组越界cf居然给我报MLE??这个题题意特别纠结,一开始一直不懂添加的边长是多长... 题意:给你一些点,然后给一些边,注意没有重边 环, ...

  7. codeforces 456 E. Civilization(并查集+数的直径)

    题目链接:http://codeforces.com/contest/456/problem/E 题意:给出N个点,M条边,组成无环图(树),给出Q个操作,操作有两种: 1 x,输出x所在的联通块的最 ...

  8. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  9. 关押罪犯 and 食物链(并查集)

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...

随机推荐

  1. codeforces 723D: Lakes in Berland

    Description The map of Berland is a rectangle of the size n × m, which consists of cells of size 1 × ...

  2. SQL Server修改代理作业的下次运行时间

    有这个现象,如果我把服务器时间调快2天运行作业,那么会发现作业的下次运行时间会变成两天+1的时间,即使是把服务器时间调正常后,这个下次运行时间也是无法调回来的 那么,要修改会正常的下次作业时间,可以这 ...

  3. GridView控件RowDataBound事件的一个实例

    实现点击两个按钮,跳转到同一个界面,HyperLink显示不同的东西,主要代码段如下 前台代码: <asp:TemplateField HeaderText="操作"> ...

  4. AngularJs $q 承诺与延迟

    $q 一个帮助处理异步执行函数的服务.当他们做完处理时,使用它们的返回值(或异常). 受 Kris Kowa’s Q 的启发,这是一个实现promise/deferred对象的启用. $q的两种方式- ...

  5. javascript undefined 和void0

    underfine === void 0 并不完全成立 undefined不是关键字  不是保留字   在IE低版本下可以被赋值 所以代码中一般以void 0 代替undefined

  6. MYSQL select查询练习题

    10. 查询Score表中的最高分的学生学号和课程号.(子查询或者排序) select sno,cno from score where degree=(select max(degree) from ...

  7. CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡

    一.简介 VS/NAT原理图: 二.系统环境 实验拓扑: 系统平台:CentOS 6.3 Kernel:2.6.32-279.el6.i686 LVS版本:ipvsadm-1.26 keepalive ...

  8. BufferedReader类

    BufferedReader类用于从缓冲区中读取内容,多有的输入字节数据都将放在缓冲区中. BufferedReader中定义的构造方法只能接收字符输入流的实例,所以必须使用字符输入流和字节输入流的转 ...

  9. SVN中Branch和Merge实践

    参考资料:http://blog.csdn.net/eggcalm/article/details/6606520 branch主要用于新功能的开发,开发过程中不断从trunk merge revis ...

  10. Python基本运算符

    Python基本运算符 什么是操作符? 简单的回答可以使用表达式4 + 5等于9,在这里4和5被称为操作数,+被称为操符. Python语言支持操作者有以下几种类型. 算术运算符 比较(即关系)运算符 ...