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. 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS

    2400: Spoj 839 Optimal Marks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 567  Solved: 202[Submit ...

  2. 配置jdk相关的记录

    1.8.0_60JAVA_HOME=/usr/local/java/jdk1.8.0_60JRE_HOME=${JAVA_HOME}/jreCLASSPATH=.:${JAVA_HOME}/lib:$ ...

  3. 【poj1568】 Find the Winning Move

    http://poj.org/problem?id=1568 (题目链接) 题意 两人下4*4的井字棋,给出一个残局,问是否有先手必胜策略. Solution 极大极小搜索.. 这里有个强力优化,若已 ...

  4. Bzoj2007 [Noi2010]海拔

    Time Limit: 20 Sec  Memory Limit: 552 MB Submit: 2380  Solved: 1130 Description YT市是一个规划良好的城市,城市被东西向 ...

  5. java编译错误 程序包javax.servlet不存在javax.servlet.*

    java编译错误 程序包javax.servlet不存在javax.servlet.* 编译:javac Servlet.java 出现 软件包 javax.servlet 不存在 软件包javax. ...

  6. <base href="<%=basePath%>

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  7. PHP之:多图上传

    撰写日期:2016-6-30 15:17:35 Thursday 参考 http://a3147972.blog.51cto.com/2366547/1381136 (08-05ThinkPHP+sw ...

  8. Dword、LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR

    DWORD:本来被定义为unsigned long,DWORD的含义就是双字,一个字是2字节,双字就是32字节. 但是在C/C++中,经常会用到把一个指针转换成数字储存,然后再将其传唤为指针调用.那么 ...

  9. 【Alpha版本】 第五天 11.11

    一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 昨天完成任务 今天完成任务 周末+下周一要做任务 问题困难 心得体会 胡泽善 完成了账户信息修改界面 完成管理员的三大界面框架.完成管理 ...

  10. Mysql学习笔记(五)数据查询之测试sql部分。

    正文之前,介绍mysql一些很有趣的命令. 快速的创建表,并填充表数据. create table test like  已经有的表名: inset into test select * from f ...