题目

给一片森林,\(q\) 个询问,每个询问两个点,

问将这两个点所在的集合连接起来组成的新集合,它的最远两点的距离的期望值是多少。


分析

首先将以每个点为根的最大深度求出来,然后对于两棵树,

只有超过两棵树直径的最大值才可能产生新的直径,

那么直接求 \(d[x]+d[y]\geq mx\) 的 \(d[x]+d[y]\),

用小的集合查询然后记忆化就可以做到 \(O(Q\sqrt{n}\log{n})\)


代码

#include <cstdio>
#include <cctype>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
const int N=100011; typedef long long lll;
map<pair<int,int>,lll>uk; vector<int>K[N];
struct node{int y,next;}e[N<<1]; vector<lll>F[N];
int col[N],f[N],g[N],dp[N],as[N],n,m,Q,et=1,upd,len[N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int max(int a,int b){return a>b?a:b;}
void dfs1(int x,int fa){
col[x]=upd;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x),dp[upd]=max(dp[upd],f[x]+f[e[i].y]+1);
if (f[x]<f[e[i].y]+1) g[x]=f[x],f[x]=f[e[i].y]+1;
else if (g[x]<f[e[i].y]+1) g[x]=f[e[i].y]+1;
}
}
void dfs2(int x,int fa){
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa){
if (f[x]==f[e[i].y]+1){
if (f[e[i].y]<g[x]+1) g[e[i].y]=f[e[i].y],f[e[i].y]=g[x]+1;
else if (g[e[i].y]<g[x]+1) g[e[i].y]=g[x]+1;
}else{
if (f[e[i].y]<f[x]+1) g[e[i].y]=f[e[i].y],f[e[i].y]=f[x]+1;
else if (g[e[i].y]<f[x]+1) g[e[i].y]=f[x]+1;
}
dfs2(e[i].y,x);
}
}
int main(){
n=iut(); m=iut(); Q=iut();
for (int i=1;i<=m;++i){
int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
for (int i=1;i<=n;++i)
if (!col[i]) ++upd,dfs1(i,0),dfs2(i,0);
for (int i=1;i<=n;++i) K[col[i]].push_back(f[i]);
for (int i=1;i<=upd;++i) sort(K[i].begin(),K[i].end());
for (int i=1;i<=upd;++i){
len[i]=K[i].size(),F[i].resize(len[i]+1);
for (int j=len[i];j;--j)
F[i][j-1]=F[i][j]+K[i][j-1];
}
for (int i=1;i<=Q;++i){
int x=col[iut()],y=col[iut()];
if (x==y) {printf("-1\n"); continue;}
if (len[x]>len[y]) swap(x,y);
if (uk.count(make_pair(x,y))) {printf("%.8lf\n",uk[make_pair(x,y)]/(1.0*len[x]*len[y])); continue;}
lll now=max(dp[x],dp[y]),ans=now*len[x]*len[y];
for (int j=0;j<len[x];++j){
int pos=lower_bound(K[y].begin(),K[y].end(),now-K[x][j])-K[y].begin();
ans+=F[y][pos]+(len[y]-pos)*(K[x][j]-now+1);
}
uk[make_pair(x,y)]=ans;
printf("%.8lf\n",ans/(1.0*len[x]*len[y]));
}
return 0;
}

#直径#CF804D Expected diameter of a tree的更多相关文章

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

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

  2. Codeforces 804D Expected diameter of a tree(树的直径 + 二分 + map查询)

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

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

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

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

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

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

  6. codeforces804D Expected diameter of a tree

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

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

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

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

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

  9. leetcode 124. Binary Tree Maximum Path Sum 、543. Diameter of Binary Tree(直径)

    124. Binary Tree Maximum Path Sum https://www.cnblogs.com/grandyang/p/4280120.html 如果你要计算加上当前节点的最大pa ...

  10. 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. win32 - 使用CreateRemoteThread调用dll上的函数(建立管道)

    Dll: // dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #i ...

  2. XILINX SDK烧录FLASH报错不支持旧版hw_server

    最近频繁遇到SDK报错,说是不支持hw_server旧版本,此时打开vivado识别的时候也是一样报错,可能原因是我电脑安装了多个版本的VIVADO导致的,那么怎么解决呢? 打开任务管理器,kill ...

  3. 数据库运维 | 携程分布式图数据库NebulaGraph运维治理实践

    作者简介:Patrick Yu,携程云原生研发专家,关注非关系型分布式数据存储及相关技术. 背景 随着互联网世界产生的数据越来越多,数据之间的联系越来越复杂层次越来越深,人们希望从这些纷乱复杂的数据中 ...

  4. Python实现snap:对齐多张遥感影像的空间范围

      本文介绍基于Python中ArcPy模块,实现基于栅格图像批量裁剪栅格图像,同时对齐各个栅格图像的空间范围,统一其各自行数与列数的方法.   首先明确一下我们的需求.现有某一地区的多张栅格遥感影像 ...

  5. Java 多线程------例子(1) --创建 三个窗口 买票 总票数为 100张 使用继承Thread类的方式

    1 package com.bytezero.threadexer; 2 3 4 5 /** 6 * 7 * 创建 三个窗口 买票 总票数为 100张 使用继承Thread类的方式 8 * @auth ...

  6. Java //在150之内 是三的倍数 输出Zzz 是5个倍数输出 Lll 是7的倍数输出zlzl

    1 //在150之内 是三的倍数 输出Zzz 是5个倍数输出 Lll 是7的倍数输出zlzl 2 int i =1; 3 for(i = 1; i<=150;i++) 4 { 5 System. ...

  7. C++ String //string字符串查找和替换 比较 存取 修改单个字符 插入和删除 string字串

    1 //string字符串查找和替换 比较 存取 修改单个字符 插入和删除 string字串 2 #include <iostream> 3 #include<string> ...

  8. pycharm/Intellij idea双击打不开,没有反应,下列方法亲测有用!

    第一种方法: 看看你的微软C++运行库是不是误删了.....我就这么干过...以前有个软件捆绑这个 安装了 结果我后来给删了 ,导致我pycharm 和intellij idea全都打不开 !!!各位 ...

  9. Go和TinyGo

    Go和TinyGo是两种不同的Go语言编译器,它们之间有以下几点区别: 目标平台: Go:Go语言编译器主要面向通用计算机平台,如Windows.Linux.macOS等. TinyGo:TinyGo ...

  10. C#泛型的类型参数约束

    常用约束 约束告知编译器类型参数必须具备的功能. 在没有任何约束的情况下,类型参数可以是任何类型. 编译器只能假定 System.Object 的成员,它是任何 .NET 类型的最终基类. 如果客户端 ...