Codeforces 804D Expected diameter of a tree
3 seconds
256 megabytes
standard input
standard output
Pasha is a good student and one of MoJaK's best friends. He always have a problem to think about. Today they had a talk about the following problem.
We have a forest (acyclic undirected graph) with n vertices and m edges. There are q queries we should answer. In each query two vertices v and u are given. Let V be the set of vertices in the connected component of the graph that contains v, and U be the set of vertices in the connected component of the graph that contains u. Let's add an edge between some vertex
and some vertex in
and compute the value d of the resulting component. If the resulting component is a tree, the value d is the diameter of the component, and it is equal to -1 otherwise. What is the expected value of d, if we choose vertices a and b from the sets uniformly at random?
Can you help Pasha to solve this problem?
The diameter of the component is the maximum distance among some pair of vertices in the component. The distance between two vertices is the minimum number of edges on some path between the two vertices.
Note that queries don't add edges to the initial forest.
The first line contains three integers n, m and q(1 ≤ n, m, q ≤ 105) — the number of vertices, the number of edges in the graph and the number of queries.
Each of the next m lines contains two integers ui and vi (1 ≤ ui, vi ≤ n), that means there is an edge between vertices ui and vi.
It is guaranteed that the given graph is a forest.
Each of the next q lines contains two integers ui and vi (1 ≤ ui, vi ≤ n) — the vertices given in the i-th query.
For each query print the expected value of d as described in the problem statement.
Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6. Let's assume that your answer is a, and the jury's answer is b. The checker program will consider your answer correct, if
.
3 1 2
1 3
3 1
2 3
-1
2.0000000000
5 2 3
2 4
4 3
4 2
4 1
2 5
-1
2.6666666667
2.6666666667
In the first example the vertices 1 and 3 are in the same component, so the answer for the first query is -1. For the second query there are two options to add the edge: one option is to add the edge 1 - 2, the other one is 2 - 3. In both ways the resulting diameter is 2, so the answer is 2.
In the second example the answer for the first query is obviously -1. The answer for the second query is the average of three cases: for added edges 1 - 2 or 1 - 3 the diameter is 3, and for added edge 1 - 4 the diameter is 2. Thus, the answer is
.
题意:
给出一个森林,q次询问,每次问把x,y两点所属的树之间任意连接一条边形成新的树的直径的期望,如果x和y在同一棵树中输出-1;
代码:
//这题算出复杂度也就解出来了。先枚举一棵树中的节点然后二分找另一棵树中的节点满足两个节点之间的距离不小于max(树1直径,
//树2直径),他们的贡献就是各自在自己树中最远能到达的端点的距离相加再+1,否则贡献就是max(树1直径,树2直径),这样看似是
//q*n*long(n),但是注意到所有的树的大小总和是n所以最坏是sqrt(n)棵树每棵树大小是sqrt(n),所以是q*sqrt(n)*long(n);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN=;
int fa[MAXN],head[MAXN],tot,n,cnt,m,q,d[MAXN],f[MAXN],deep,o,oo,root[MAXN];
int a[MAXN],aa;
double size[MAXN];
map<pair<int,int>,double>mp;
vector<ll>v[MAXN],vv[MAXN];
struct Edge { int u,v,next; }edge[MAXN*];
void init()
{
tot=cnt=;
memset(head,-,sizeof(head));
memset(fa,-,sizeof(fa));
memset(f,,sizeof(f));
memset(d,-,sizeof(d));
}
void add(int x,int y)
{
edge[tot].u=x;edge[tot].v=y;
edge[tot].next=head[x];
head[x]=tot++;
edge[tot].u=y;edge[tot].v=x;
edge[tot].next=head[y];
head[y]=tot++;
}
void dfs1(int x,int father,int p)
{
v[p].push_back(x);
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==father) continue;
fa[y]=p;
dfs1(y,x,p);
}
}
void dfs2(int x,int father,int sum,bool w)
{
if(w!=) f[x]=max(f[x],sum);
if(sum>=deep){
deep=sum;
if(w==) o=x;
else if(w==) oo=x;
}
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==father) continue;
dfs2(y,x,sum+,w);
}
}
int main()
{
//freopen("in.txt","r",stdin);
init();
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++){
if(fa[i]!=-) continue;
fa[i]=++cnt;
v[cnt].clear();vv[cnt].clear();
dfs1(i,,cnt);
root[cnt]=i;
}
for(int i=;i<=cnt;i++){
deep=;
dfs2(root[i],,,);
deep=;
dfs2(o,,,);
d[i]=deep;
dfs2(oo,,,);
aa=v[i].size();
for(int j=;j<aa;j++) a[j]=f[v[i][j]];
v[i].clear();
for(int j=;j<aa;j++) v[i].push_back(a[j]);
sort(v[i].begin(),v[i].end());
a[aa]=;
for(int j=aa-;j>=;j--) a[j]=a[j+]+v[i][j]+;
for(int j=;j<=aa;j++) vv[i].push_back(a[j]);
}
while(q--){
int x,y;
scanf("%d%d",&x,&y);
if(fa[x]==fa[y]) printf("-1\n");
else{
pair<int,int>p1(fa[x],fa[y]);
if(mp[p1]>) printf("%.6f\n",mp[p1]);
else{
double ans=;
int xx=fa[x],yy=fa[y];
if(v[xx].size()<=v[yy].size()){
for(int i=;i<v[xx].size();i++){
ll tmp=lower_bound(v[yy].begin(),v[yy].end(),max(d[xx],d[yy])-v[xx][i]-)-v[yy].begin();
ans+=(vv[yy][tmp]+v[xx][i]*(v[yy].size()-tmp))+tmp*max(d[xx],d[yy]);
}
}else{
for(int i=;i<v[yy].size();i++){
ll tmp=lower_bound(v[xx].begin(),v[xx].end(),max(d[xx],d[yy])-v[yy][i]-)-v[xx].begin();
ans+=(vv[xx][tmp]+v[yy][i]*(v[xx].size()-tmp))+tmp*max(d[xx],d[yy]);
}
}
double tmp1=v[xx].size(),tmp2=v[yy].size();
ans/=(tmp1*tmp2);
printf("%.6f\n",ans);
mp[p1]=ans;
}
}
}
return ;
}
Codeforces 804D Expected diameter of a tree的更多相关文章
- Codeforces 804D Expected diameter of a tree(树的直径 + 二分 + map查询)
题目链接 Expected diameter of a tree 题目意思就是给出一片森林, 若把任意两棵树合并(合并方法为在两个树上各自任选一点然后连一条新的边) 求这棵新的树的树的直径的期望长度. ...
- Codeforces 804D Expected diameter of a tree(树形DP+期望)
[题目链接] http://codeforces.com/contest/804/problem/D [题目大意] 给你一个森林,每次询问给出u,v, 从u所在连通块中随机选出一个点与v所在连通块中随 ...
- Codeforces 840D Expected diameter of a tree 分块思想
Expected diameter of a tree 我们先两次dfs计算出每个点能到达最远点的距离. 暴力计算两棵树x, y连边直径的期望很好求, 我们假设SZ(x) < SZ(y) 我们枚 ...
- CodeForces 805F Expected diameter of a tree 期望
题意: 给出一个森林,有若干询问\(u, v\): 从\(u, v\)中所在子树中随机各选一个点连起来,构成一棵新树,求新树直径的期望. 分析: 回顾一下和树的直径有关的东西: 求树的直径 从树的任意 ...
- CF804D Expected diameter of a tree 树的直径 根号分治
LINK:Expected diameter of a tree 1e5 带根号log 竟然能跑过! 容易想到每次连接两个联通快 快速求出直径 其实是 \(max(D1,D2,f_x+f_y+1)\) ...
- Codeforces Round #411 (Div. 1) D. Expected diameter of a tree
题目大意:给出一个森林,每次询问给出u,v,问从u所在连通块中随机选出一个点与v所在连通块中随机选出一个点相连,连出的树的直径期望(不是树输出-1).(n,q<=10^5) 解法:预处理出各连通 ...
- codeforces804D Expected diameter of a tree
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 543. Diameter of Binary Tree
https://leetcode.com/problems/diameter-of-binary-tree/#/description Given a binary tree, you need to ...
- LeetCode 543. Diameter of Binary Tree (二叉树的直径)
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...
随机推荐
- 【Py大法系列--01】20多行代码生成你的微信聊天机器人
前言 近期Stack Overflow公布了一项调查显示,Python已经成了发展最快的主流编程语言,Python搭乘着数据科学和机器学习以及人工智能的浪潮,席卷了整个技术圈.越来越多的人想了解.想学 ...
- hexo主题中添加相册功能
博客已迁移至http://lwzhang.github.io. 基本上所有的hexo主题默认都没有实现相册功能,一方面相册功能的需求较少,毕竟hexo主要是写博客用的:另一方面实现相册功能比较麻烦,比 ...
- Scrum Meeting 5 -2014.11.11
放假过掉一大半.大家都努力赶着进度,算法实现基本完成.可能还有些细小的改动,但也可以统一进入测试阶段了. 今天叫了部分在校人员开了个小会.任务决定以测试为主,同时开始进行服务器的部署. 在之前尝试服务 ...
- 20172311『Java程序设计』课程 结对编程练习_四则运算第一周阶段总结
20172311『Java程序设计』课程 结对编程练习_四则运算第一周阶段总结 结对伙伴 学号 :20172307 姓名 :黄宇瑭 伙伴第一周博客地址: http://www.cnblogs.com/ ...
- C#窗体随机四则运算 (第四次作业)
---恢复内容开始--- 增量内容:1)处理用户的错误输入,比如输入字母或符号等,处理除法运算中分母为0的情况,处理结果为负数的情况,保证是小学水平不出现负数,比如不能出现5-8=-3这种情况:2)用 ...
- Software Defined Networking(Week 2, part 1)
History of SDN 1.1 - 1.2 本节讨论从上世纪八十年代时到现在为止出现的SDN的思想和发展历史.了解历史,可以明白技术后面的成因以及一些原则,并从架构上去大致掌握.了解一些主旨. ...
- (二)Jmeter各部件的作用
JMeter主要组件介绍 1.测试计划(Test Plan)是使用 JMeter 进行测试的起点,它是其它 JMeter 测试元件的容器. 2.线程组(Thread Group)代表一定数量的并发用户 ...
- Laravel 5.1 中的异常处理器和HTTP异常处理 abort()
原文 http://laravelacademy.org/post/1867.html 错误和异常是处理程序开发中不可回避的议题,在本地开发中我们往往希望能捕获程序抛出的异常并将其显示打印出来,以便 ...
- Flyway的第一次认识
1. 引言 想到要管理数据库的版本,是在实际产品中遇到问题后想到的一种解决方案,当时各个环境的数据库乱作一团,没有任何一个人(开发.测试.维护人员)能够讲清楚当前环境下的数据库是哪个版本,与哪个版本 ...
- BAT等公司必问的8道Java经典面试题,你都会了吗?
工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1.“知其然不知其所以然”.做了多年技术,开发了很多业务应用,但似乎并 ...