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;
}
京公网安备 11010502036488号