dfs+链式前向星存图
题目分析:我们以每个叶子节点去寻找能够构成连通块的结点,如果当前节点已经是k的倍数了,那么就不用去寻找其他节点,也就是说连接父节点的那条边可以去掉,然后一直自下而上的去寻找,如果当前子树的权值和是k的倍数,那么说明这个子树可以自成一体不用去寻找其他节点来合并了
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e6 + 10; ll a[maxn], head[maxn], tot, ans, n, k; struct node { int to, w, next; } edge[maxn]; void add(ll u, ll v, ll w) { edge[++tot].to = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot; } void dfs(ll s, ll e) { for (int i = head[s]; ~i; i = edge[i].next) { if (edge[i].to == e) continue; dfs(edge[i].to, s); if (a[edge[i].to]) { ans += edge[i].w; a[s] += a[edge[i].to]; } } a[s] %= k; } int main() { memset(head, -1, sizeof(head)); scanf("%lld%lld", &n, &k); for (int i = 1; i <= n; ++i) { scanf("%lld", &a[i]); a[i] %= k; } for (int i = 1; i < n; ++i) { ll u, v, w; scanf("%lld%lld%lld", &u, &v, &w); add(u, v, w); add(v, u, w); } dfs(1, 0); printf("%lld\n", ans); return 0; }