Jumping Monkey
题意
一个树,每个点有一个权重, u u u可以跳到 v v v当且仅当 v v v的权重是 u → v u \to v u→v这条路径的最大值。问你从每一个点出发,最多可以经过多少个不同的点。
题解
假设点权最大的点为 u u u,那么不管从哪个点开始跳,最终一定会跳到这个点,因为 u u u是点权最大的点,所以到 u u u以后就停了。所以 u u u一定是每一个点出发的最优解的终点(对现有的所有的可达点的贡献都是1),我们将 u u u从树上去掉,并把相连的边去掉,对于剩下的每个联通块都递归做(因为这样做每一步都是最优的,所以到某一节点被取出,这个点就是最优解)。
发现这么递归算不好维护进行,因此反向考虑这个过程(做等价变换):按点权从小到大枚举结点 u u u,并将 u u u作为所有和 u u u相连的(已经枚举过的)连通块的根。建一棵新树,结点的深度就是res。
将 u u u作为所有和 u u u相连的(已经枚举过的)连通块的根,这样相当于他的子树中的每一个点都可以到 u u u这个点, u u u会使得每个点的深度加一(相当于可以这种跳法多到一个点,做了一个树上差分,最后可以得到res)。
可以暴力枚举每一个点的临点,是否是前面出现过的,如果是就找到那个子树的树根并连到当前这个点(用一个并查集维护),最后dfs求一下深度即可。
Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath>
#include <stack>
#include <iomanip>
#include <deque>
#include <sstream>
#define x first
#define y second
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 4 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx, h1[N];
void add(int h[], int a, int b, int v = 0) {
e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N], b[N];
int f[N];
int dep[N];
bool cmp(int u, int v) {
return a[u] < a[v];
}
int find(int x) {
return f[x] == x ? x : f[x] = find(f[x]);
}
void dfs(int u, int p) {
dep[u] = p;
for (int i = h1[u]; ~i; i = ne[i]) {
int j = e[i];
dfs(j, p + 1);
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T -- ) {
cin >> n;
for (int i = 1; i <= n; i ++ ) h[i] = h1[i] = -1;
idx = 0;
for (int i = 0; i < n - 1; i ++ ) {
int a, b;
cin >> a >> b;
add(h, a, b), add(h, b, a);
}
for (int i = 1; i <= n; i ++ ) cin >> a[i], b[i] = f[i] = i;
sort(b + 1, b + n + 1, cmp);
for (int i = 1; i <= n; i ++ ) {
int j = b[i];
for (int k = h[j]; ~k; k = ne[k]) {
int u = e[k];
if (a[u] < a[j]) {
u = find(u);
f[u] = j;
add(h1, j, u);
}
}
}
dfs(b[n], 1);
for (int i = 1; i <= n; i ++ ) cout << dep[i] << endl;
}
return 0;
}