3717. 【NOI2014模拟7.2】火车(train)

Description

A国有n个城市,城市之间有一些双向道路相连,并且城市两两之间有唯一路径。现在有火车在城市a,需要经过m个城市。火车按照以下规则行驶:每次行驶到还没有经过的城市中在m个城市中最靠前的。现在小A想知道火车经过这m个城市后所经过的道路数量。

Input

第一行三个整数n、m、a,表示城市数量、需要经过的城市数量,火车开始时所在位置。

接下来n-1行,每行两个整数x和y,表示x和y之间有一条双向道路。

接下来一行m个整数,表示需要经过的城市。

Output

一行一个整数,表示火车经过的道路数量。

Sample Input

5 4 2

1 2

2 3

3 4

4 5

4 3 1 5

Sample Output

9

Data Constraint

这里写图片描述

Solution

首先要注意本题的一个大坑,题目说每次行驶到还没有经过的城市中在m个城市中最靠前的。也就是说如果在走第一个点的时候经过了第二个点,那么第二个点就不用再走了。
考虑用动态树维护所有点在序列中的位置,未出现则为无穷大。
每次找到下一个没有被访问的点,不断找链上最小值,标记为已访问并把权值改为无穷大。
但实际上可以直接用倍增lca,然后再用并查集维护这个点是否走过。这个操作其实很简单,首先我们将所有的节点的并查集父亲赋成这棵树的父亲,然后再将必须要经过的点的并查集的父亲赋成它自己,因为这样做的时候,我们每次找并查集的父亲的时候如果找到了一个必须要走的点就必须退出找父亲,那么就可以直接将它标记了,至于那些我们不需要经过的点就可以不用管了。

Code1

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 500010
using namespace std;
int n,m,x,y,now,a[N],f[N][20],fa[N],lca;
int t[N*2],nx[N*2],ls[N],d[N],s[N];
bool bz[N];
ll ans=0;
void add(int x,int y){
    t[++t[0]]=y;
    nx[t[0]]=ls[x];
    ls[x]=t[0];
}
int getlca(int x,int y){
    if(d[y]>d[x]) swap(x,y);
    int dep=d[x]-d[y];
    for(int i=19;i>=0;i--) 
        if(dep&(1<<i)) x
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值