题目链接 Expected diameter of a tree

题目意思就是给出一片森林,

若把任意两棵树合并(合并方法为在两个树上各自任选一点然后连一条新的边)

求这棵新的树的树的直径的期望长度。

我们对每棵独立的树,对于这棵树的每一个点$u$,求出$f[u]$

$f[u]$为这棵树上离$u$最远的点到$u$的距离。

同时我们求出每棵树上的树的直径的长度

现在合并两棵树$A$和$B$的时候,合成的新的树的直径$C$其实有三种情况。

对$A$树中的某点$x$,$B$树中的某点$y$

1、可能是$A$树中树的直径,长度为$d[A]$

2、可能是$B$树中树的直径,长度为$d[B]$

3、可能是:离$A$树中点$x$最远的点$-->x-->y-->$离$B$树中点$y$最远的点

长度为$f[x] + f[y] + 1$

三种情求最大值即可

在枚举所有情况的时候,对每个点x枚举y

我们要求的是$max(f[x] + f[y] + 1, d[A], d[B])$

其中令$max(d[A], d[B]) = Z$

那么我们要求的就是$max(f[x] + f[y] + 1, Z)$

我们两两枚举$x$和$y$显然是要超时的,怎么优化呢?

我们可以在两棵树中选一棵规模较小的树,枚举这棵树上的每个点$x$

对于另一棵树$B$,二分一个临界值,在这个临界值两边

我分别取较大的$f[x] + f[y] + 1$ 或是 $Z$

这道题数据规模比较大,询问的时候的给出两个点,一个点在$A$树上,一个点在$B$树上

所以他如果不友好一点,在某两棵点很多的树上选很多不同的点对来构成很多次询问。

但事实上他们的本质是同一个询问,这个时候还是有可能超时。

那么我们就把每棵独立的树编号,每次处理完一个询问,把答案塞到map里面

那么下一次处理到本质相同的询问的时候,就可以直接拿出来了。

(这道题真的很锻炼代码能力,当初做的时候调了好几个小时……)

 #include <bits/stdc++.h>

 using namespace std;

 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = ; int n, m, q, L, R, nowdep, treenum = ;
int father[N], tr[N], c[N], f[N], d_max[N];
vector <int> v[N], tree[N], dis[N], g[N]; set < int > st;
map < int, int > mp;
map < pair<int, int> , double > ans;
map < pair<int, int> , int > flag; int getfather(int x){
return father[x] ? father[x] = getfather(father[x]) : x;
} void dfs(int x, int fa, int dep){
f[x] = max(f[x], dep);
for (auto u : v[x]){
if (u == fa) continue;
dfs(u, x, dep + );
}
} void dfs1(int x, int fa, int dep){
if (dep > nowdep){
L = x;
nowdep = dep;
} for (auto u : v[x]){
if (u == fa) continue;
dfs1(u, x, dep + );
}
} void dfs2(int x, int fa, int dep){
if (dep > nowdep){
R = x;
nowdep = dep;
} for (auto u : v[x]){
if (u == fa) continue;
dfs2(u, x, dep + );
}
} int main(){ scanf("%d%d%d", &n, &m, &q);
memset(father, , sizeof father);
rep(i, , m){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
int fa = getfather(x), fb = getfather(y);
if (fa != fb) father[fa] = fb;
} rep(i, , n) st.insert(getfather(i)); for (auto u : st){
mp[u] = ++treenum;
tr[treenum] = u;
} rep(i, , n){
int x = getfather(i);
tree[mp[x]].push_back(i);
c[i] = mp[x];
} memset(f, , sizeof f); rep(i, , treenum){
L = ; nowdep = -;
dfs1(tree[i][], , );
R = , nowdep = -;
dfs2(L, , );
dfs(L, , );
dfs(R, , );
for (auto u : tree[i]) dis[i].push_back(f[u]);
sort(dis[i].begin(), dis[i].end());
rep(j, , (int)tree[i].size() - ){
if (j == ) g[i].push_back(dis[i][j]);
else g[i].push_back(g[i][j - ] + dis[i][j]);
}
d_max[i] = dis[i][(int)tree[i].size() - ];
} ans.clear();
flag.clear(); for (; q--; ){
int x, y;
scanf("%d%d", &x, &y);
if (c[x] == c[y]){
puts("-1");
continue;
}
int na = c[x], nb = c[y];
if ((int) tree[na].size() > (int) tree[nb].size()) swap(na, nb);
if (flag[{na, nb}]){
printf("%.12f\n", ans[{na, nb}]);
continue;
} LL X = ;
LL Y = (LL) tree[na].size() * tree[nb].size();
LL Z = max(d_max[na], d_max[nb]);
for (auto u1 : tree[na]){
LL A = lower_bound(dis[nb].begin(), dis[nb].end(), Z - - f[u1]) - dis[nb].begin();
X += (LL) A * Z +
(LL) (g[nb][(int)tree[nb].size() - ] + (int)tree[nb].size() - A - (A ? g[nb][A - ] : )) +
(f[u1]) * ((LL) tree[nb].size() - A);
} double cnt_ans = (double) X / (double) Y;
printf("%.12f\n", cnt_ans); flag[{na, nb}] = ;
ans[{na, nb}] = cnt_ans;
} return ;
}

Codeforces 804D Expected diameter of a tree(树的直径 + 二分 + map查询)的更多相关文章

  1. Codeforces 804D Expected diameter of a tree

    D. Expected diameter of a tree time limit per test 3 seconds memory limit per test 256 megabytes inp ...

  2. CF804D Expected diameter of a tree 树的直径 根号分治

    LINK:Expected diameter of a tree 1e5 带根号log 竟然能跑过! 容易想到每次连接两个联通快 快速求出直径 其实是 \(max(D1,D2,f_x+f_y+1)\) ...

  3. Codeforces 804D Expected diameter of a tree(树形DP+期望)

    [题目链接] http://codeforces.com/contest/804/problem/D [题目大意] 给你一个森林,每次询问给出u,v, 从u所在连通块中随机选出一个点与v所在连通块中随 ...

  4. Codeforces 840D Expected diameter of a tree 分块思想

    Expected diameter of a tree 我们先两次dfs计算出每个点能到达最远点的距离. 暴力计算两棵树x, y连边直径的期望很好求, 我们假设SZ(x) < SZ(y) 我们枚 ...

  5. CodeForces 805F Expected diameter of a tree 期望

    题意: 给出一个森林,有若干询问\(u, v\): 从\(u, v\)中所在子树中随机各选一个点连起来,构成一棵新树,求新树直径的期望. 分析: 回顾一下和树的直径有关的东西: 求树的直径 从树的任意 ...

  6. Codeforces Round #411 (Div. 1) D. Expected diameter of a tree

    题目大意:给出一个森林,每次询问给出u,v,问从u所在连通块中随机选出一个点与v所在连通块中随机选出一个点相连,连出的树的直径期望(不是树输出-1).(n,q<=10^5) 解法:预处理出各连通 ...

  7. Codeforces Round #379 (Div. 2) E. Anton and Tree 树的直径

    E. Anton and Tree time limit per test 3 seconds memory limit per test 256 megabytes input standard i ...

  8. codeforces804D Expected diameter of a tree

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  9. codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

    J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...

随机推荐

  1. Vue基础指令集锦

    v-model双向绑定数据 <input type="text" v-model="msg"> {{msg}} ###v-on 事件 <div ...

  2. linux下GPIO的用户层操作(sysfs)

    linux的GPIO通过sysfs为用户提供服务,下面是linux kernel里的说明文档,学习一下. GPIO Sysfs Interface for Userspace ============ ...

  3. 爬虫之Scrapy和分页

    下一页和详情页的处理 xpath提取时 注意: 结合网页源代码一起查找 不用框架的爬取 获取下一页 自带href属性 1)首页有下一页 next_url = element.xpath('.//a[t ...

  4. shell中变量字符串的截取 与 带颜色字体、背景输出

    字符串截取 假设我们定义了一个变量为:file=/dir1/dir2/dir3/my.file.txt 可以用${ }分别替换得到不同的值:${file#*/}:删掉第一个 /及其左边的字符串:dir ...

  5. statistics-skewed data

    参考文献: http://www.statisticshowto.com/skewed-distribution/ left/negatively-skewed distributions : box ...

  6. 全链路spring cloud sleuth+zipkin

    http://blog.csdn.net/qq_15138455/article/details/72956232 版权声明:@入江之鲸 一.About ZipKin please google 二. ...

  7. python集合、字符编码、bytes与二进制

    集合 用括号表示{ },可以包含多个元素,用逗号分割 用途 用于关系运算 集合特点 1.每个元素是不可变类型 2.没有重复的元素 3.无序 应用 1.set去重 set(names)的功能是将列表转换 ...

  8. c++中vector容器的功能及应用。

    vector基本操作:  1.头文件 #include<vector>. 注:一定要加上using namespace std;  2.vector对象的创建: vector<int ...

  9. Git使用规范流程(转载)

    作者: 阮一峰 日期: 2015年8月 5日 团队开发中,遵循一个合理.清晰的Git使用流程,是非常重要的. 否则,每个人都提交一堆杂乱无章的commit,项目很快就会变得难以协调和维护. 下面是Th ...

  10. iOS学习笔记47-Swift(七)泛型

    一.Swift泛型介绍 泛型是为Swift编程灵活性的一种语法,在函数.枚举.结构体.类中都得到充分的应用,它的引入可以起到占位符的作用,当类型暂时不确定的,只有等到调用函数时才能确定具体类型的时候可 ...