CF455C Civilization (并查集)
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:
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:
Output
For each event of the first type print the answer on a separate line. Sample test(s)
Input
6 0 6 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 (并查集)的更多相关文章
- cf455C Civilization (并查集)
并查集维护每个联通块的直径和最小的最大深度,每次连得时候连的肯定是最大深度最小的那两个点 #pragma GCC optimize(3) #include<bits/stdc++.h> # ...
- Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径
C. Civilization Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/probl ...
- Codeforces 455C Civilization(并查集+dfs)
题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...
- CodeForces 455C Civilization (并查集+树的直径)
Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...
- CodeForces - 455C Civilization (dfs+并查集)
http://codeforces.com/problemset/problem/455/C 题意 n个结点的森林,初始有m条边,现在有两种操作,1.查询x所在联通块的最长路径并输出:2.将结点x和y ...
- CodeForces 455C Civilization(并查集+树直径)
好久没有写过图论的东西了,居然双向边要开两倍空间都忘了,不过数组越界cf居然给我报MLE??这个题题意特别纠结,一开始一直不懂添加的边长是多长... 题意:给你一些点,然后给一些边,注意没有重边 环, ...
- codeforces 456 E. Civilization(并查集+数的直径)
题目链接:http://codeforces.com/contest/456/problem/E 题意:给出N个点,M条边,组成无环图(树),给出Q个操作,操作有两种: 1 x,输出x所在的联通块的最 ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- 关押罪犯 and 食物链(并查集)
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...
随机推荐
- 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 × ...
- SQL Server修改代理作业的下次运行时间
有这个现象,如果我把服务器时间调快2天运行作业,那么会发现作业的下次运行时间会变成两天+1的时间,即使是把服务器时间调正常后,这个下次运行时间也是无法调回来的 那么,要修改会正常的下次作业时间,可以这 ...
- GridView控件RowDataBound事件的一个实例
实现点击两个按钮,跳转到同一个界面,HyperLink显示不同的东西,主要代码段如下 前台代码: <asp:TemplateField HeaderText="操作"> ...
- AngularJs $q 承诺与延迟
$q 一个帮助处理异步执行函数的服务.当他们做完处理时,使用它们的返回值(或异常). 受 Kris Kowa’s Q 的启发,这是一个实现promise/deferred对象的启用. $q的两种方式- ...
- javascript undefined 和void0
underfine === void 0 并不完全成立 undefined不是关键字 不是保留字 在IE低版本下可以被赋值 所以代码中一般以void 0 代替undefined
- MYSQL select查询练习题
10. 查询Score表中的最高分的学生学号和课程号.(子查询或者排序) select sno,cno from score where degree=(select max(degree) from ...
- CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡
一.简介 VS/NAT原理图: 二.系统环境 实验拓扑: 系统平台:CentOS 6.3 Kernel:2.6.32-279.el6.i686 LVS版本:ipvsadm-1.26 keepalive ...
- BufferedReader类
BufferedReader类用于从缓冲区中读取内容,多有的输入字节数据都将放在缓冲区中. BufferedReader中定义的构造方法只能接收字符输入流的实例,所以必须使用字符输入流和字节输入流的转 ...
- SVN中Branch和Merge实践
参考资料:http://blog.csdn.net/eggcalm/article/details/6606520 branch主要用于新功能的开发,开发过程中不断从trunk merge revis ...
- Python基本运算符
Python基本运算符 什么是操作符? 简单的回答可以使用表达式4 + 5等于9,在这里4和5被称为操作数,+被称为操符. Python语言支持操作者有以下几种类型. 算术运算符 比较(即关系)运算符 ...