[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1316
[算法]
点分治
由于边权较大,笔者在计算时使用了STL-set
注意当询问为0时,要输出"Yes"
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 10010 #define MAXQ 110 struct Edge { int to,w,nxt; } e[MAXN<<1]; int i,n,q,tot,root,u,v,w,len; int size[MAXN],head[MAXN],weight[MAXN],sum[MAXN],val[MAXN],a[MAXQ]; bool visited[MAXN],ans[MAXQ]; inline void addedge(int u,int v,int w) { tot++; e[tot] = (Edge){v,w,head[u]}; head[u] = tot; } inline void getroot(int u,int fa,int total) { int i,v; size[u] = 1; weight[u] = 0; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (fa != v && !visited[v]) { getroot(v,u,total); size[u] += size[v]; weight[u] = max(weight[u],size[v]); } } weight[u] = max(weight[u],total - size[u]); if (weight[u] < weight[root]) root = u; } inline void dfs(int u,int fa) { int i,v,w; val[++len] = sum[u]; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (v != fa && !visited[v]) { sum[v] = sum[u] + w; dfs(v,u); } } } inline void calc(int u) { int i,j,k,v,w; set< int > s; s.clear(); s.insert(0); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v]) { sum[v] = w; len = 0; dfs(v,u); for (j = 1; j <= len; j++) { for (k = 1; k <= q; k++) { if (s.find(a[k] - val[j]) != s.end()) ans[k] = true; } } for (j = 1; j <= len; j++) s.insert(val[j]); } } } inline void work(int u) { int i,v; visited[u] = true; calc(u); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (!visited[v]) { root = 0; getroot(v,0,size[v]); work(root); } } } int main() { scanf("%d%d",&n,&q); for (i = 1; i < n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } for (i = 1; i <= q; i++) scanf("%d",&a[i]); root = 0; size[0] = weight[0] = n; getroot(1,0,n); work(root); for (i = 1; i <= q; i++) printf((ans[i] || a[i] == 0) ? "Yes " : "No "); return 0; }