Expected diameter of a tree

我们先两次dfs计算出每个点能到达最远点的距离。

暴力计算两棵树x, y连边直径的期望很好求, 我们假设SZ(x) < SZ(y)

我们枚举 x 的每个端点, 二分找到分界点, 复杂度为SZ(x) * log(SZ(y))

其实我们对于每次询问我们记忆化一下就可以啦。

这是因为对于SZ(x)小于 sqrt(n)的询问, 我们直接暴力求就好啦, 复杂度q * SZ(x) * log(SZ(y))

对于SZ(x) > sqrt(n) 这样的 x , 个数绝对不超过sqrt(n)所以如果两两之间的答案全部算出来的

最坏复杂度是sqrt(n) * sqrt(n) / 2 * sqrt(n) * log(n) == n * sqrt(n) * log(n) 。 所以直接记忆化就好啦。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < ) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} const int B = ; map<PII, LL> Map;
int treecnt, belong[N];
vector<int> tree[N];
vector<LL> sum[N]; int n, m, q, maxdis[N], dia[N], son[N];
vector<int> G[N];
bool root[N]; void dfs(int u, int fa, int idx) {
belong[u] = idx;
son[idx]++;
for(auto& v : G[u]) {
if(v == fa) continue;
dfs(v, u, idx);
chkmax(maxdis[u], maxdis[v] + );
}
} void dfs2(int u, int fa, int maxup) {
chkmax(maxdis[u], maxup + );
int mx0 = maxup, mx1 = -inf;
for(auto& v : G[u]) {
if(v == fa) continue;
if(maxdis[v] > mx0) mx1 = mx0, mx0 = maxdis[v];
else if(maxdis[v] > mx1) mx1 = maxdis[v];
}
for(auto& v : G[u]) {
if(v == fa) continue;
if(maxdis[v] == mx0) dfs2(v, u, mx1 + );
else dfs2(v, u, mx0 + );
}
} LL calc(int u, int v) {
LL ans = ;
LL maxdia = max(dia[u], dia[v]);
for(auto& d : tree[u]) {
int p = upper_bound(ALL(tree[v]), maxdia - d - ) - tree[v].begin();
ans += p * maxdia;
if(p < SZ(tree[v])) {
ans += (SZ(tree[v]) - p) * (d + ) + sum[v].back();
if(p - >= ) ans -= sum[v][p - ];
}
}
return ans;
} int main() {
scanf("%d%d%d", &n, &m, &q);
for(int i = ; i <= m; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = ; i <= n; i++)
if(!belong[i]) dfs(i, , ++treecnt), root[i] = true;
for(int i = ; i <= n; i++) if(root[i]) dfs2(i, , -);
for(int i = ; i <= n; i++) {
tree[belong[i]].push_back(maxdis[i]);
chkmax(dia[belong[i]], maxdis[i]);
}
for(int i = ; i <= treecnt; i++) {
sort(ALL(tree[i]));
sum[i].resize(SZ(tree[i]));
sum[i][] = tree[i][];
for(int j = ; j < SZ(sum[i]); j++)
sum[i][j] = sum[i][j - ] + tree[i][j];
}
for(int i = ; i <= q; i++) {
int u, v; scanf("%d%d", &u, &v);
u = belong[u]; v = belong[v];
if(son[u] > son[v]) swap(u, v);
if(u == v) {
puts("-1");
} else {
if(Map.find(mk(u, v)) == Map.end()) Map[mk(u, v)] = calc(u, v);
printf("%.12f\n", 1.0 * Map[mk(u, v)] / son[u] / son[v]);
}
}
return ;
} /*
*/

Codeforces 840D Expected diameter of a tree 分块思想的更多相关文章

  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. Codeforces 804D Expected diameter of a tree(树的直径 + 二分 + map查询)

    题目链接 Expected diameter of a tree 题目意思就是给出一片森林, 若把任意两棵树合并(合并方法为在两个树上各自任选一点然后连一条新的边) 求这棵新的树的树的直径的期望长度. ...

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

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

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

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

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

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

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

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

  7. codeforces804D Expected diameter of a tree

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

  8. 543. Diameter of Binary Tree

    https://leetcode.com/problems/diameter-of-binary-tree/#/description Given a binary tree, you need to ...

  9. 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 ...

随机推荐

  1. 记录腾讯云中矿机病毒处理过程(重装系统了fu*k)

    刚想学学kafka,登录与服务器看看把,谁知ssh特别慢,很奇怪,我以为是我网速问题,断了wifi,换了网线,通过iterm想要ssh root@x.x.x.x,但是上不去? 就tm的很奇怪了,登录腾 ...

  2. Django 视图系统

    Django 视图系统 概念 一个视图函数,简称视图,是一个简单的Python函数,用于接受Web请求并返回Web响应. 通常将视图函数写在project或app目录中的名为views.py文件中 简 ...

  3. zabbix误报交换机重启

    交换机的sysUpTime是由一个32-bit的counter来计数的,单位是0.01秒,所以最大时间为496天,过了496天就溢出,变成0,然后又重新计算时间,所以zabbix误报. snmpwal ...

  4. elastalert 配置post告警方式(备忘)

      最近在做把elk告警日志发送到kinesis 流,供后续数据分析处理使用........ 基于尽量不修改elastalert ,把修改工作放到接收端服务的原则.计划把elk的告警数据通过远程api ...

  5. 越光后端开发——ygapi(1.新建项目ygapi、新建MySQL数据库yg、项目连接数据库)

    1.新建MySQL数据库 show databases;//查看已经有的数据库 create database yg; 2.新建项目ygapi 1.使用pycharm新建django项目取名ygapi ...

  6. SQL学习指南之查询入门

    查询语句 select语句由几个组件或者说子句构成.不过在MySQL中,只有一种子句是必不可少的(select子句),通常的查询语句会至少包含6个子句中的2~3个.下面的表列出了用于不同目的的各个子句 ...

  7. Python多进程与单进程效率对比

    运行环境:Python3 in win10 先生成200个测试文件 # generate.py i = 0 while i < 200: o = open("test\\" ...

  8. 老男孩Python全栈学习 S9 日常作业 006

    1.使用循环打印以下效果: 1: * ** *** **** ***** 2: ***** **** *** ** * 3: * *** ***** ******* ********* for i i ...

  9. Docker:手动制作镜像 [五]

    一.制作docker镜像的步骤 1.启动容器安装软件服务 2.将安装好服务的容器commit提交为镜像 3:.启动新容器来测试新提交的镜像 二.制作支持ssh远程登录的docker镜像 1.启动容器安 ...

  10. Docker:dockerfile构建php项目 [八]

    一.把项目封装成docker镜像的步骤 把项目封装成docker镜像的步骤: 1.先运行一个基础容器,手动制作docker镜像 2.编写dockerfile,构建镜像 3.测试运行 二.dockerf ...