题目描述
有一个 nn 个点 n-1n−1 条边的无向连通图迷宫,其中有些点上面有人
现在所有人的目标都是逃离这个迷宫,而迷宫的出口是 11 号点,每一时刻,会依次发生以下的事情:
在点 xx 上的人选择一个点 f(x)f(x) 作为目标,要求 f(x)f(x) 必须是 xx,或者与 xx 有边相连的点,且对于 x
eq yx̸=y,有 f(x)
eq f(y)f(x)̸=f(y)
在点 xx 上的人移动到 f(x)f(x)
在点 11 号点上的人成功逃脱,从这个游戏里消失
现在你需要求的是:让所有人都成功逃脱至少需要多少时间
输入描述
第一行一个正整数 nn (1leq nleq 10^5)(1≤n≤105)
第二行 nn 个整数 a_1...a_na1...an,a_i=1ai=1 表示一开始第 ii 个点上有人,a_i=0ai=0 则表示没有,保证 a_1=0a1=0
接下来 n-1n−1 行,每行两个正整数 (u,v)(u,v) 描述图中的一条无向边
输出描述
输出让所有人成功逃脱至少需要多少时间
样例输入 1
4
0 0 1 1
1 2
2 3
2 4
样例输出 1
3
题意就是一些人在一棵树上移动,要移动到1号点的最小时间。
emmm
发现我的思维真的水 qwq
感觉有点正难则反的意思吧,同时向上的情况不好考虑,那就考虑一下向下走的情况,也就是每个节点从根节点走向自己的位置,
但让上一个走完的deep的时间,这一个点就要走deep加上1的时间,因为两个点不能同事在根节点。
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 const int maxn=1e5+5;
5 int n, a[maxn];
6 int ans,dis;
7 vector <int> G[maxn];
8
9 int deep[maxn], fa[maxn];
10 void dfs(int u)
11 {
12 for (auto v : G[u]) if (v != fa[u])
13 {
14 deep[v] = deep[u] + 1;
15 fa[v] = u;
16 dfs(v);
17 }
18 }
19
20 int main()
21 {
22 scanf("%d",&n);
23 for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
24 for (int i = 1; i < n; i++)
25 {
26 int u,v;
27 scanf("%d%d", &u, &v);
28 G[u].push_back(v);
29 G[v].push_back(u);
30 }
31 deep[1] = 0; dfs(1);
32 vector <int> vec;
33 for (int i = 1; i <= n; i++) if (a[i]) vec.push_back(i);
34 sort(vec.begin(), vec.end(),[](int a,int b)->bool{return deep[a]>deep[b];});
35 for (auto it : vec)
36 {
37 ans = max(ans, dis + deep[it]);
38 ++dis;
39 }
40 printf("%d
", ans);
41 return 0;
42 }