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;
}