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 ...
随机推荐
- [buaa-SE-2017]个人作业-期末总结
个人作业-期末总结 Part1: 阅读作业 在这一部分,首先我将说说我对这次阅读作业中每篇文章的理解,最后结合这次团队项目的经理谈谈自己对软件开发的看法. 1. No Silver Bullet 文章 ...
- 2018-2019-20172329 《Java软件结构与数据结构》第九周学习总结
2018-2019-20172329 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十五章-图 一.图及无向图 1.图的相关概 ...
- Leetcode题库——26.删除排序数组中的重复项
@author: ZZQ @software: PyCharm @file: removeDuplicates.py @time: 2018/9/23 13:51 要求: 给定一个排序数组,你需要在原 ...
- Python对list去重
Python对list去重 方法一 新建新的列表,利用not in命令去重.这种方法看起来不够简便,但是保留了原列表中的顺序.代码如下: list1 = [1,2,3,4,1,1,2,5,4,3] l ...
- 300道随机四则运算小程序(java编写)
这是由Java编写的300道随机四则运算小程序, 运算数范围为0~100(不包括100),运算结果保留两位小数. 程序代码: import java.util.*; class Yunsuan{ pu ...
- 用户数以及psp
小组名称:好好学习 小组成员:林莉 王东涵 胡丽娜 宫丽君 项目名称: 记账本 alpha发布48小时以后用户数如何,是否达到预期目标,为什么,是否需要改进,如何改进(或理性估算). 首先我 ...
- Delphi函数的out、var等关键字的作用,和使用场景
问题描述 Delphi函数的out.var等关键字的作用,和使用场景 Delphi函数的out.var等关键字的作用,和使用场景,我知道var是作为传值调用,但是像out这个关键字又是什么作用呢? 解 ...
- Centos7 FPM 安装mysql8
参考http://tn.51cto.com/article/647 http://www.jb51.net/article/138787.htm 转载: 卸载centos自带的mariadb rpm ...
- 卸载Visual Studio最佳方法难道真的是重装系统?
卸载Visual Studio最佳方法难道真的是重装系统? 卸载Visual Studio最佳方法难道真的是重装系统? 使用TotalUninstaller貌似也没有效果,默认卸载的,程序列表里面还是 ...
- java.io.FileNotFoundException: generatorConfig.xml (系统找不到指定的文件。)
在使用MyBatis的逆向工程生成代码时,一直报错java.io.FileNotFoundException: generatorConfig.xml (系统找不到指定的文件.),如图 文件结构如下: ...