博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LCA][数学]JZOJ 4794 富爷说是一棵树
阅读量:5948 次
发布时间:2019-06-19

本文共 2492 字,大约阅读时间需要 8 分钟。

Description

富爷说来一棵树,于是大头栽了一棵树。树大了,有n个点和n - 1条边,任意两个点都是联通的,点的标号为1 - n。爱树的大头和富爷在树上安居乐业,但大头住在u,而富爷住在v,他们都很不高兴,因为u到v有且只有一条简单路径。
当然了,树王富爷找到了解决办法,他打算带着大头再给树建一条边(保证不是自环),而且他们会在n * (n - 1) / 2的方案中随机选择一种。
但,要让富爷和大头开心是有条件的。只有新建边之后,富爷去大头家以及大头去富爷家存在两条路径不会走相同的边时,他们才会呵呵(也就是说 存在一个简单环包含u和v)。
不开心的事情选择忘记。当富爷和大头开心时,你能得到愉快值等于环的大小。所以,你要告诉富爷和大头,当他们开心时(只考虑在环内),他们的期望愉悦值。
 

Input

第 1 行包含 2个正整数n 和 m (2≤n,m≤100000),表示树有n 个点,以及有m组询问。
接下来n−1行描述了一些双联通边,每行包含两个整数ai和bi,(1≤ai,bi≤n),表示第i条路连接的两个点。
最后m行描述富爷和大头,第i行包含两个整数ui和vi,(1≤ui,vi≤n,ui≠vi),表示富爷和大头分别住在哪里。

Output

对于每组询问你需要输出如果富爷和大头开心的期望愉快度。你的答案与标准答案误差不能超过1e-6。
 

Sample Input

输入1: 4 3 2 4 4 1 3 2 3 1 2 3 4 1 输入2: 3 3 1 2 1 3 1 2 1 3 2 3

Sample Output

输出1: 4.00000000 3.00000000 3.00000000 输出2: 2.50000000 2.50000000 3.00000000 【输入输出样例 2 说明】 1、(1,2)和(2,3)均能让富爷和大头开心,则期望愉悦值为(2 + 3)/ 2 = 2.5 2、(1,3)和(2,3)均能让富爷和大头开心,则期望愉悦值为(2 + 3)/ 2 = 2.5 3、(2,3)能使富爷和大头开心,则期望愉悦值为3  
 

Data Constraint

20% n,m <= 2000
40% n,m <= 10^5 树是随机的
60% n,m <= 10^5 每个点的度数均为2
100% n,m <= 10^5

 

 分析

题意大概就是树上加一条边使一对点在一个简单环中的期望环长

我们发现,其实答案就是dist(u,v)*size[u]*size[v]+f[u]*size[v]+f[v]*size[u]

dist就是u到v的路径长度,size是子树大小,f是子树内所有点到子树的根的距离和

分母也显然是size[u]*size[v]

然后我们发现size和f都是可以预处理的,dist可以直接得出

然后如果u,v有祖孙关系的话,子树就不是往常意义的子树(假设v是祖先),那就是除了有u的那棵子树以外的都是v的子树

所以要处理一个g[v]来搞这种情况

 
#include 
#include
#include
#include
using namespace std;typedef long long ll;const int N=1e5+10;struct Edge { int v,nx;}e[2*N];int cnt,list[N];int fa[N][20],dep[N];ll f[N],g[N],sz[N];int n,m,logn;void Add(int u,int v) { e[++cnt]=(Edge){v,list[u]};list[u]=cnt; e[++cnt]=(Edge){u,list[v]};list[v]=cnt;}void DFS(int u,int fat) { fa[u][0]=fat;dep[u]=dep[fat]+1;sz[u]=1; for (int i=list[u];i;i=e[i].nx) if (e[i].v!=fat) { DFS(e[i].v,u); sz[u]+=sz[e[i].v]; f[u]+=f[e[i].v]+sz[e[i].v]; }}void DFS_G(int u,int fa) { if (fa) g[u]=f[fa]-f[u]-sz[u]+g[fa]+(n-sz[fa]); for (int i=list[u];i;i=e[i].nx) if (e[i].v!=fa) DFS_G(e[i].v,u);}int LCA(int u,int v) { for (int i=logn;i>=0;i--) if (dep[fa[u][i]]>=dep[v]) u=fa[u][i]; if (u==v) return v; for (int i=logn;i>=0;i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0];}int Witch_Son(int u,int v) { for (int i=logn;i>=0;i--) if (dep[fa[u][i]]>dep[v]) u=fa[u][i]; return u;}int main() { scanf("%d%d",&n,&m); for (int i=1,u,v;i
View Code

 

 

转载于:https://www.cnblogs.com/mastervan/p/10574864.html

你可能感兴趣的文章
xml格式文件解析
查看>>
ios百度地图-路径规划
查看>>
Python高效编程技巧
查看>>
配置Eclipse使用maven构建项目默认JDK为1.8
查看>>
博客分享:程序员提升自我必备
查看>>
【细品架构10/100】架构由术至道的转变(1)
查看>>
网页显示405 Method not allowed问题
查看>>
jsp内置对象以及jsp动作
查看>>
Struts上路_09-数据类型转换
查看>>
定制CentOS
查看>>
Android Eclipse 修改默认查看图片的打开方式
查看>>
CMake与动态链接库(dll, so, dylib)
查看>>
myeclipse(eclipse)乱码处理
查看>>
SpringBoot 过滤器, 拦截器, 监听器 对比及使用场景
查看>>
数据库索引探索
查看>>
MYSQl left join 联合查询效率分析
查看>>
struts2使用json需要注意的问题
查看>>
客户端的socket是否需要bind?
查看>>
Comparator进行排序
查看>>
IOS自动进行View标记
查看>>