(color{#0066ff}{题目描述})
给定一棵有n个点的树
询问树上距离为k的点对是否存在。
(color{#0066ff}{输入格式})
n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径
接下来m行每行询问一个K
(color{#0066ff}{输出格式})
对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)
(color{#0066ff}{输入样例})
2 1
1 2 2
2
(color{#0066ff}{输出样例})
AYE
(color{#0066ff}{数据范围与提示})
对于30%的数据n<=100
对于60%的数据n<=1000,m<=50
对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000
(color{#0066ff}{题解})
每次找重心,删去递归子树
对于每个子树,dfs出到子树根(重心)的距离
对于同一子树的,会有重复的路径,那不是答案,但是也统计了,所以在枚举孩子的时候要减回去,这部分答案在递归子树的时候会被统计
每次把所有的子树的dis扔进数组里
(O(n^2)收集答案)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
char ch; int x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
struct node {
int to, dis;
node *nxt;
node(int to = 0, int dis = 0, node *nxt = NULL): to(to), dis(dis), nxt(nxt) {}
void *operator new (size_t) {
static node *S = NULL, *T = NULL;
return (S == T) && (T = (S = new node[1024]) + 1024), S++;
}
};
const int maxn = 2e5 + 10;
int f[maxn], tmp[maxn], dis[maxn], siz[maxn], can[maxn];
bool vis[maxn];
node *head[maxn];
int n, sum, m, root, num;
void add(int from, int to, int dis) {
head[from] = new node(to, dis, head[from]);
}
void getdis(int x, int fa, int d) {
tmp[++num] = d;
dis[x] = d;
for(node *i = head[x]; i; i = i->nxt)
if(i->to != fa && !vis[i->to])
getdis(i->to, x, d + i->dis);
}
void calc(int x, int d, int flag) {
num = 0;
dis[x] = d;
getdis(x, 0, dis[x]);
for(int i = 1; i <= num; i++)
for(int j = 1; j <= num; j++)
if(i != j)
can[tmp[i] + tmp[j]] += flag;
}
void getroot(int x, int fa) {
siz[x] = 1;
f[x] = 0;
for(node *i = head[x]; i; i = i->nxt) {
if(i->to == fa || vis[i->to]) continue;
getroot(i->to, x);
siz[x] += siz[i->to];
f[x] = std::max(f[x], siz[i->to]);
}
f[x] = std::max(f[x], sum - siz[x]);
if(f[x] < f[root]) root = x;
}
void work(int x) {
calc(x, 0, 1);
vis[x] = true;
for(node *i = head[x]; i; i = i->nxt)
if(!vis[i->to]) {
calc(i->to, i->dis, -1);
sum = siz[i->to];
root = 0;
getroot(i->to, 0);
work(root);
}
}
int main() {
n = in(), m = in();
int x, y, z;
for(int i = 1; i <= n - 1; i++) {
x = in(), y = in(), z = in();
add(x, y, z), add(y, x, z);
}
f[0] = n, sum = n;
getroot(1, 0), work(root);
while(m --> 0) printf(can[in()]? "AYE
" : "NAY
");
return 0;
}