首页 > 其他分享 >P6227 [BalticOI 2019 Day1] 山谷

P6227 [BalticOI 2019 Day1] 山谷

时间:2023-07-18 21:14:19浏览次数:39  
标签:P6227 int res top LCA Day1 2019 lca 补给点

P6227 [BalticOI 2019 Day1] 山谷

Description

给一棵树,一个根,一些特殊补给点,一些询问。求解如下问题:断掉一条边 \(u\to v\),这样以后你能否从给定的 \(R_i\) 走到根,若能输出 escaped。不能到达根且不能到达任何一个特殊补给点输出 oo。若不能到达根但可以到达特殊补给点输出边权和最小值。

Solution

我们考虑断边 \(u\to v\) 之后的情形,为方便描述我们设 \(fa_v=u\)。

我们考虑不能从给定的 \(R_i\) 走到根的情况,即 \(\operatorname{LCA}(v,R)= v\) 时,则我们有如果能走到根,则必有 \(\operatorname{LCA}(v,R)\ne v\),则第一种情况解决完毕。

下面考虑设 \(\_shop_i\) 表示 \(i\) 及 \(i\) 的子树内特殊补给点的个数,可以考虑使用 dfs 进行预处理,那么不能到达根且不能到达任何一个补给点的充要条件为 \(\operatorname{LCA}(v,R)=v\) 且 \(\_shop_v=0\)。

最后考虑最难的一种情况,即不能到达根但可以到达特殊补给点。设 \(dis_i\) 表示编号为 \(i\) 的点到根的边权和,设到达的最近特殊补给点编号为 \(id\),设 \(R\) 和 \(id\) 的 \(\operatorname{LCA}\) 为 \(\_lca\) ,设这个 \(\operatorname{LCA}\) 到 \(id\) 的距离为 \(W_{\_lca}\),则我们有 \(Ans=dis_R-dis_{\_lca}+W_{\_lca}\)。我们考虑复杂度瓶颈,即不能暴力枚举所有 \(v\) 子树内的点作为 \(\operatorname{LCA}\),则我们考虑倍增优化。

设 \(f_{i,j}\) 表示编号为 \(i\) 的点向上跳 \(2^j\) 步范围内最近的满足上段条件的 \(\operatorname{LCA}\) 所产生的贡献 \(-dis_{\_lca}+W_{\_lca}\)。则我们有如果该点为特殊补给点则 \(f_{i,0}=0\)。而后我们考虑预处理 \(f_{i,j}=\min(f_{i,j-1},f_{fat_{i,j-1},j-1})\)。

每次询问枚举跳 \(2^j\) 步,每次如果 \(dep_{fat_{x,j}}\ge dep_v\)(即不能跳出被截断的子树)就继续往上跳找答案,即 \(res=\min(res,f_{x,j})\),最后 \(ans=\min(ans,f_{v,0})\)。别忘了这时的 \(ans\) 不是最终答案,需要 \(Ans=ans+dis_R\)。得出最后的 \(Ans\)。

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,s,q,e;
const int N=2e5+7;
vector<pair<int,int> > G[N<<1];
int top[N<<1];
int fa[N<<1],bgs[N<<1],dep[N<<1],siz[N<<1];
int U[N<<1],V[N<<1],W[N<<1];
int shop[N<<1];
int f[N][30];
int _shop[N<<1];
int fat[N][30];
int dis[N];

void dfs(int x,int fat){
	if(shop[x]) f[x][0]=0;
	_shop[x]=shop[x];
  dep[x]=dep[fat]+1;
  fa[x]=fat;siz[x]=1;
  for(auto it:G[x]){
    int k=it.first,w=it.second;
    if(k!=fat){
    	dis[k]=dis[x]+w;
      dfs(k,x);
      f[x][0]=min(f[x][0],f[k][0]+w);
      _shop[x]+=_shop[k];
      siz[x]+=siz[k];
      if(siz[k]>siz[bgs[x]]) bgs[x]=k;
    }
  }
}

void DFS(int x,int fat,int tp){
  top[x]=tp;
  if(bgs[x]){
  	DFS(bgs[x],x,tp);
  }
  for(auto it:G[x]){
    int k=it.first;
    if(k!=fat&&k!=bgs[x]) DFS(k,x,k);
  }
}

int lca(int x,int y){
  while(top[x]^top[y]) dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
  return dep[x]<dep[y]?x:y;
}

void work(int I,int R){
	int u=U[I],v=V[I];
	if(fa[v]!=u) swap(u,v);
	if(lca(v,R)!=v) return printf("escaped\n"),void();
	if(lca(v,R)==v&&_shop[v]==0) return printf("oo\n"),void();
	int x=R;
	int res=0x3f3f3f3f3f3f3f3fll;
	for(int j=18;j>=0;j--){
		if(dep[fat[x][j]]>=dep[v]){
			res=min(res,f[x][j]);
			x=fat[x][j];
		}
	}
	res=min(res,f[v][0]);
	res+=dis[R];
	printf("%lld\n",res);
}

void debug(){
	for(int i=1;i<=n;i++) printf("%lld ",dis[i]);
	puts("");
}

signed main(){
	memset(f,0x3f,sizeof f);
	scanf("%lld%lld%lld%lld",&n,&s,&q,&e);
	for(int i=1;i<n;i++){
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		G[u].push_back(make_pair(v,w)),G[v].push_back(make_pair(u,w));
		U[i]=u,V[i]=v,W[i]=w;
	}
	for(int i=1;i<=s;i++) {int pos;scanf("%lld",&pos);shop[pos]=1;}
	dfs(e,0),DFS(e,0,e);
	for(int i=1;i<=n;i++){
		f[i][0]-=dis[i];
	}
	for(int i=1;i<=n;i++) fat[i][0]=fa[i];
	for(int j=1;j<=18;j++){
		for(int i=1;i<=n;i++){
			fat[i][j]=fat[fat[i][j-1]][j-1];
			f[i][j]=min(f[i][j-1],f[fat[i][j-1]][j-1]);
		}
	}
	for(int i=1;i<=q;i++) {int I,R;scanf("%lld%lld",&I,&R),work(I,R);}
}

标签:P6227,int,res,top,LCA,Day1,2019,lca,补给点
From: https://www.cnblogs.com/Zimo233/p/17564127.html

相关文章

  • 「JOISC 2019 Day4」蛋糕拼接 3 题解
    先考虑这个式子:\(\sum_{j=1}^{M}|C_{k_{j}}-C_{k_{j+1}}|\)一定是在\(C\)有序时取到,具体证明很简单各位读者自己证明。那么现在式子变成:\(\sum{V}+2\times({C_{\max}-C_{\min}})\)这个时候一个常见的技巧是将\(C\)排序。这个时候就可以定义状态:\(dp_{i,j}=\s......
  • Day11(2023.07.18)
    行程8:45    到达上海市信息安全测评认证中心(黄浦区陆家浜路1308号)9:00  改文件11:30--13:00   吃饭休息13:00 创建项目,熟悉软件,生成报告等..17:00      下班......
  • [GUET-CTF2019]KO
    直接给了一个txt文件,打开直接是ook的编码不知道为啥在随波上面直接用brainfuck就直接出来又用了一下ook的解码网站也是一样的网址:Brainfuck/Ook!Obfuscation/Encoding[splitbrain.org]结束......
  • 远程登陆virtualbox虚拟机windows server 2019
    1.virtualbox网络设置2.启用远程桌面3.获取远程ip4.本机使用mstsc远程登陆......
  • [GXYCTF2019]Ping Ping Ping
    [GXYCTF2019]PingPingPing题目来源:buuctf题目类型:web涉及考点:命令执行1.题目页面如下:我们将其作为参数传入,/?ip=127.0.0.1,回显如下:接下来通过命令行查看目录:/?ip=127.0.0.1;ls2.发现了flag.php,直接查看/?ip=127.0.0.1;catflag.php发现空格被过滤了,我们采取以下......
  • 【2023.07.17】牛客&第四范式多校Day1(华中科技大学Round)过题小记
    D-Chocolate(博弈论)12分钟过题。签到。K-Subdivision(图论、搜索)1小时21分过题,签到。如果给定的是一棵树的话,新增的点一定位于连接叶子节点的那条边上、否则就是已有的点。然而这是一张图,所以我们可以使用\(\ttbfs\)将其近似的转化为一棵树:当某个点(非其父节点)被第二次遍历......
  • 【2023.07.14】Atcoder:past201912 - 第一回 アルゴリズム実技検定(div4+区域赛难度)过题
    G-Division解法一:位运算+状压枚举(赛时思路)范围显然,可以跑\(2^n\)的算法,考虑位运算状态压缩。以\(\mathcalO(2^n\cdot2^n)\)的复杂度分别枚举位于第一组、第二组中的人,随后计算每一种分组的快乐值,代码较长,赛时敲了半个小时,不过好在一发过了。总结:其实代码里面的剪枝完......
  • [强网杯 2019]随便注
    [强网杯2019]随便注题目来源:buuctf题目类型:web涉及考点:SQL注入、堆叠注入1.先简单介绍一下堆叠注入在SQL语句中,分号用来表示一条语句的结束。那么当我们结束一条语句之后,继续构造下一条语句,可不可以一起执行呢?这就是堆叠注入,简单来说,就是把多条SQL语句一起上传。例如,我们......
  • 算法练习-day18
    二叉树654.最大二叉树题意:给定一个不重复的整数数组 nums。 最大二叉树 可以用下面的算法从 nums递归地构建:创建一个根节点,其值为 nums中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值右边的 子数组后缀上 构建右子树。返回 nums......
  • 题解 P7250 [BalticOI 2012 Day1] 山峰
    通过观察,可以发现此题和最小生成树十分相似(两个地点之间途经的最小值最大)。于是可以考虑这么做:通过bfs将每一个块预处理出来,并记录其编号、高度、类型(是否为高地)以及边缘的点。将每一个块按高度从大到小排序。依次枚举每个块:对于当前要处理的块,枚举其边界的所有点,......