[CSP-S模拟测试]:木叶下(图论)
题目传送门(内部题77)
输入格式
第一行一个整数$n$,表示原先的树的点数接下来$n-1$行每行两个整数$a,b$,表示原先的树上的$n-1$条边,保证这$n-1$条边形成一棵树。
接下来一行一个整数$m$,表示不同的方案数。
接下来$m$行每行两个整数$u,v$,表示$m$个不同的加边方案,每行的方案表示在那一行给出的$u,v$之间加一条边。注意如果$u=v$,说明加了一条自环导致加边失败,此时最后留下$0$个点。
输出格式
$m$行,第$i$行一个整数表示第$i$次询问的答案。
样例
见下发文件
数据范围与提示
所有的测试点,$n\leqslant 200,000,m\leqslant 200,000$
第$1$个测试点,保证一开始编号相差为$1$的任意两个点之间有一条边,也就是说给出的树形态是一条链。
第$2,3,4$个测试点,所有的加边方案满足$u=v$。第$2$个测试点还满足$n\leqslant 500$
第$5,6,7$个测试点,$n\leqslant 500,m\leqslant 500$
第$8$个测试点,所有的加边方案满足$u,v$在原树上相邻,也就是有边直接相连。
第$9$个测试点,所有的加边方案满足$u,v$在原树上距离为$2$,也就是说,$u!=v$,且存在点$z$,既和$u$相邻也和$v$相邻。
第$10,11,12$个测试点,树是随机生成的,随机方式的伪代码为:
$for\ i\ in\ [2...n]$
$addedge(i,rand()\%(i-1)+1)$
也就是说,对$2$到$n$这$n-1$个点,分别随机选择一个编号更小的点与其连边。
第$13,14,15$个测试点,所有的加边方案满足$u=1$
第$10,13,16,17$个测试点,不会出现$u=v$的情况。
第$18$到$20$个测试点,无特殊性质。
题解
可以发现在加边失败(加入自环)的情况下,答案就是树的直径的一半(上取整)。
加边之后无非就是缩掉那个环后新的数的直径的一半(上取整),但是显然时间不允许我们这么做,于是考虑怎么快速求出加边之后的贡献。
不妨把环上的点看成黑点,其它的点看成白点,设$dis[i]$表示从$i$到最近黑点的距离,那么答案即为$\max(dis[i])$。
那么则需要算出来对于每一个黑点,其控制了哪些白点。
不妨设$g[i]$表示从$i$出发向其子树内走,能走的最深的距离。
对于每个点,预处理出来其儿子中最大的三个$g[i]$,并记录分别是谁。
这样就能在$\Theta(1)$的时间复杂度内计算出不允许第一步走向黑点的情况下能一直向下走的最远距离。
但是显然我们不能直接计算所有黑点。
利用树上倍增优化算法。
不妨设$q[i]$表示从$i$的父亲走向其子树而不经过$i$所能够到达的最远距离,预处理即可。
然后利用倍增对$q[i]$进行树上路径取$\max$即可。
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[400001];
int head[200001],cnt;
int n,m;
pair<int,int> mx[200001][4];
int mxdep;
int w[200001];
int depth[200001],fa[200001][21],maxn[200001][21];
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
int dfs1(int x,int fa)
{
depth[x]=depth[fa]+1;
for(int i=head[x];i;i=e[i].nxt)
{
if(e[i].to==fa)continue;
int flag=dfs1(e[i].to,x);
if(flag>mx[x][3].second)mx[x][3]=make_pair(e[i].to,flag);
if(mx[x][3].second>mx[x][2].second)swap(mx[x][3],mx[x][2]);
if(mx[x][2].second>mx[x][1].second)swap(mx[x][2],mx[x][1]);
}
mxdep=max(mxdep,mx[x][1].second+mx[x][2].second+1);
return mx[x][1].second+1;
}
int find1(int x,int y)
{
if(x==y||!y)return 0;
for(int i=1;i<=3;i++)if(mx[x][i].first&&mx[x][i].first!=y)return mx[x][i].second;
return 0;
}
int find2(int x,int _,int __)
{
if(x==_||x==__||!_||!__)return 0;
for(int i=1;i<=3;i++)if(mx[x][i].first&&mx[x][i].first!=_&&mx[x][i].first!=__)return mx[x][i].second;
return 0;
}
void dfs2(int x,int fat)
{
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fat)
{
maxn[e[i].to][0]=find1(x,e[i].to);
fa[e[i].to][0]=x;
w[e[i].to]=max(w[x]+1,maxn[e[i].to][0]+1);
for(int j=1;j<=20;j++)
{
fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1];
maxn[e[i].to][j]=max(maxn[e[i].to][j-1],maxn[fa[e[i].to][j-1]][j-1]);
}
dfs2(e[i].to,x);
}
}
int LCA(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
int res=mx[y][1].second;
for(int i=20;i>=0;i--)
if(depth[fa[y][i]]>=depth[x])
{
res=max(res,maxn[y][i]);
y=fa[y][i];
}
if(x==y)return max(res,w[x]);
res=max(res,mx[x][1].second);
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
res=max(res,maxn[y][i]);
res=max(res,maxn[x][i]);
x=fa[x][i];
y=fa[y][i];
}
res=max(res,find2(fa[x][0],x,y));
res=max(res,w[fa[x][0]]);
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs1(1,0);
dfs2(1,0);
scanf("%d",&m);
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
if(u==v)printf("%d\n",(mxdep+1)/2);
else printf("%d\n",LCA(u,v));
}
return 0;
}
rp++
[CSP-S模拟测试]:木叶下(图论)的更多相关文章
- [CSP-S模拟测试]:Graph(图论+贪心)
题目描述 给定一张$n$个点$m$条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通你想在这张图上进行若干次旅游,每次旅游可以任选一个点$x$作为起点,再走到一个与 $x$直接有边相连的点$ ...
- [CSP-S模拟测试]:环(图论+期望)
题目传送门(内部题79) 输入格式 第一行读入两个整数$n,e$表示节点数及$cwystc$已确定的有向边边数. 接下来$e$行,每行两个整数$x,y$描述$cwystc$确定的边. 输出格式 输出一 ...
- [CSP-S模拟测试]:连连看(图论+容斥)
题目传送门(内部题74) 输入格式 输入文件$link.in$ 第一行三个整数$n,m,k$,之间用空格隔开,$n,m$表示地图行数和列数,$k$表示每个方块周围相邻的位置(至多有$4$个,至少有$2 ...
- Mac下Jmeter快速安装与入门-模拟测试Post请求及设置Http头
[1]去Apache官网下载 Binaries系列的最新Jmeter.gz包 [2]下载到本地之后解压缩,进入到解压之后的目录然后,找到apache-jmeter-4.0/bin/jmeter.sh ...
- [考试反思]1109csp-s模拟测试106:撞词
(撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...
- Android单元测试与模拟测试详解
测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...
- 利用Python中的mock库对Python代码进行模拟测试
这篇文章主要介绍了利用Python中的mock库对Python代码进行模拟测试,mock库自从Python3.3依赖成为了Python的内置库,本文也等于介绍了该库的用法,需要的朋友可以参考下 ...
- Mockito:一个强大的用于Java开发的模拟测试框架
https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...
- NOIP模拟测试1(2017081501)
好,今天是cgg第一次举行模拟测试,希望各位支持. 时间限制:2小时 题目链接: 题目一:水得都没名字了 题目二:车站 题目三:选数 不要觉得2小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...
随机推荐
- The order of a Tree
The order of a Tree Problem Description As we know,the shape of a binary search tree is greatly rela ...
- BeautifulSoup库的基本元素
BeautifulSoup库 <html> <body> <p class='title'></p> </body> </html&g ...
- [BZOJ 3456]城市规划(cdq分治+FFT)
[BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...
- 6.float类型 和 char 类型
float32 float64 package main import "fmt" func main() { var xxx float32 var xxxx float64 ...
- linux-导入python自定义模块的使用方法
#!/usr/bin/python # -*- coding:utf -8 -*- import os import sys sys.path.append("/h/s/compare_f& ...
- 标准库path源码解读
先看标准库 作用:关于路径的一些实用操作 https://github.com/golang/go/blob/master/src/path/path.go 源码地址 func IsAbs func ...
- 批处理遍历文件夹执行git pull
echo off & color 0A for /d %%f in (D:\www\*) do ( D: cd %%f chdir git pull ) pause 遍历D:\www\这个文件 ...
- offsetWidth clientWidth scrollWidth 的区别
了解 offsetWidth clientWidth scrollWidth 的区别 最近需要清除区分开元素的width,height及相应的坐标等,当前这篇用来区分offsetWidth clien ...
- 计算机体系结构总结_Pipeline
Textbook:<计算机组成与设计——硬件/软件接口> HI<计算机体系结构——量化研究方法> QR 在前面一节里我们有了一块简单的RISC CPU,包括 ...
- jQuery中$()可以有两个参数
jQuery(expression, [context]) 返回值:jQuery 概述 这个函数接收一个包含 CSS 选择器的字符串,然后用这个字符串去匹配一组元素. jQuery 的核心功能都是通过 ...