[英]Find the sum of weights of edges between every pair of nodes in a weighted tree
我需要找到一种有效的方法来找到加权树中所有简单路径的值的总和。 简单路径的值定义为给定简单路径中所有边的权重之和。
这是我的尝试,但它不起作用。 请告诉正确的方法。
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, ll> pil;
const int MAXN = 1e5;
int n, color[MAXN + 2];
vector<pil> adj[MAXN + 2];
ll sum1, cnt1[MAXN + 2], cnt[MAXN + 2], res;
void visit(int u, int p)
{
cnt[u] = 1;
cnt1[u] = color[u];
for (int i = 0; i < (int) adj[u].size(); ++i)
{
int v = adj[u][i].first;
ll w = adj[u][i].second;
if (v == p)
continue;
visit(v, u);
ll tmp = cnt1[v] * (n - sum1 - cnt[v] + cnt1[v]);
tmp += (cnt[v] - cnt1[v]) * (sum1 - cnt1[v]);
res += tmp * w;
cnt[u] += cnt[v];
cnt1[u] += cnt1[v];
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%d", color + i);
sum1 += color[i];
}
for (int i = 1, u, v; i < n; ++i)
{
scanf("%d %d %lld", &u, &v, &res);
adj[u].push_back(pil(v, res));
adj[v].push_back(pil(u, res));
}
res = 0;
visit(1, -1);
printf("%lld\n", res);
return 0;
}
下面是@Arjun Singh 解释的简单实现。
int64_t ans = 0;
int dfs(int node, int parent) {
int cur_subtree_size = 1;
for(int child : adj[node]) {
if(parent != child) {
int child_subtree_size = dfs(child, node);
int64_t contribution_of_cur_edge = child_subtree_size * (N - child_subtree_size) * weight[{node, child}];
ans += contribution_of_cur_edge;
cur_subtree_size += child_subtree_size;
}
}
return cur_subtree_size;
}
您可以计算最终答案中每条边的贡献。 假设一条边连接两个组件 component1 ---- component2。 那么这条边在最终答案中的贡献将是 - Vertices(component1) * Vertices(component2)*edge_weight。
没有。 可以通过运行 dfs 并计算每个顶点的子树中的顶点数轻松找到每个组件中的顶点数。 让一条边连接顶点 u 和 v。u 是 v 的父节点。那么, Vertices(v) = v 的子树中的顶点数 = Vertices(component1) Vertices(component2) = n - Vertices(v)
您可以预先计算这个子树数组。 所以最终的时间复杂度将是 O(n)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.