Title Link
meaning of the title
Judging whether there is a pair of points with distance k on the tree and the weight value of the tree edge
thinking
The point divide and conquer template problem divides and conquers the path of the point pair according to a certain point and not a certain point.
Each time the center of gravity is divided and conquered, the complexity of each solution is the size of the connected block of the non-enumerated points. If it is a chain, it is about n+2_n/2+4_n/4... n+2*n/2+4*n/4... N + 2 N / 2 + 4 N / 4... If the number of recursive layers is O(n)* by heart, then the chain should be the worst complexity. The total complexity of this problem is O(n_m_logn)O(n_m_logn)O(n_m_logn)O(n_m_logn)
The general idea of point division and conquer is to find the center of gravity by getrt, enumerate the currently selected center of gravity by dfs, and calculate the solution of the center of gravity by calc.
Code
#include <bits/stdc++.h> using namespace std; #define N 10005 #define maxn 10000005 int tot, first[N]; struct Edge { int v, w, nxt; }e[N<<1]; void add(int u, int v, int w) { e[++tot].v = v; e[tot].w = w; e[tot].nxt = first[u]; first[u] = tot; } // sum = n total number, sz[i] takes I as the root node's subtree size, and maxsz[i] represents the maximum subtree size with I as the root node // vis[i] denotes whether divide and conquer has enumerated I as the center of gravity, and rt denotes the current enumeration center of gravity. int sum, sz[N], maxsz[N], vis[N], rt; // dis[i] calculates the distance between I and rt, the last and current situation of las and now, and q records which are convenient to delete las int dis[N], las[maxn], now[N], q[N]; void getrt(int u, int fa) { sz[u] = 1, maxsz[u] = 0; for(int i = first[u]; i; i = e[i].nxt) { int v = e[i].v; if(v == fa || vis[v]) continue; getrt(v,u); sz[u] += sz[v]; maxsz[u] = max(maxsz[u], sz[v]); } maxsz[u] = max(maxsz[u], sum-sz[u]); if(maxsz[u] < maxsz[rt]) rt = u; } void getdis(int u, int fa) { now[++now[0]] = dis[u]; // printf("%d ##\n",dis[u]); for(int i = first[u]; i; i = e[i].nxt) { int v = e[i].v; int w = e[i].w; if(v == fa || vis[v]) continue; dis[v] = dis[u]+w; getdis(v,u); } } int calc(int u, int k) { int p = 0; for(int i = first[u]; i; i = e[i].nxt) { int v = e[i].v; if(vis[v]) continue; now[0] = 0; dis[v] = e[i].w; getdis(v,u); for(int j = now[0]; j; --j) { if(k-now[j] >= 0 && las[k-now[j]]) { for(int ii = 1; ii <= p; ++ii) las[q[ii]] = 0; // printf("!!!!!!\n"); return 1; } } for(int j = now[0]; j; --j) q[++p] = now[j], las[now[j]] = 1; } for(int i = 1; i <= p; ++i) las[q[i]] = 0; return 0; } int dfs(int u, int k) { // printf("%d -------\n",u); vis[u] = las[0] = 1; if(calc(u, k)) return 1; for(int i = first[u]; i; i = e[i].nxt) { int v = e[i].v; if(vis[v]) continue; maxsz[rt = 0] = sum = sz[v]; getrt(v, 0); if(dfs(rt, k)) return 1; } return 0; } int main() { int n, m; scanf("%d%d",&n,&m); for(int i = 1; i < n; ++i) { int u, v, w; scanf("%d%d%d",&u,&v,&w); add(u, v, w); add(v, u, w); } for(int i = 1; i <= m; ++i) { int k; scanf("%d",&k); maxsz[rt = 0] = sum = n; memset(vis,0,sizeof(vis)); getrt(1,0); printf("%s\n",dfs(rt, k) ? "AYE" : "NAY"); } return 0; }