题意概括
在一棵树上的每个节点出发,自己之外的叶子节点结束,求所有可能路径长度的总和(树上每条边长都为1)。
输入格式
第一行包含两个正整数
N
,
M
N,M
N,M表示树的点数与边数。
接下来
M
M
M 行,每行三个正整数表示
L
i
,
b
i
,
c
i
L_i,b_i,c_i
Li,bi,ci 分别表示树上有一条长度为
L
i
L_i
Li 的连接
b
i
,
c
i
b_i,c_i
bi,ci 两个结点的边。
输出格式
仅一行表示答案。
样例输入
5 4
1 2 1
1 3 1
2 4 2
2 5 2
样例输出
37
样例解释
可能的路径有
(
1
→
2
→
4
)
,
(
1
→
2
→
5
)
,
(
1
→
3
)
,
(
2
→
4
)
,
(
2
→
5
)
,
(
2
→
1
→
3
)
,
(
3
→
1
→
2
→
4
)
,
(
3
→
1
→
2
→
5
)
,
(
4
→
2
→
5
)
,
(
4
→
2
→
1
→
3
)
,
(
5
→
2
→
4
)
,
(
5
→
2
→
1
→
3
)
(1\to 2\to 4),(1\to 2\to 5),(1\to 3),(2\to 4),(2\to 5),(2\to 1\to 3),(3\to 1\to 2\to 4),(3\to 1\to 2\to 5),(4\to 2\to 5),(4\to 2\to 1\to 3),(5\to 2\to 4),(5\to 2\to 1\to 3)
(1→2→4),(1→2→5),(1→3),(2→4),(2→5),(2→1→3),(3→1→2→4),(3→1→2→5),(4→2→5),(4→2→1→3),(5→2→4),(5→2→1→3)。
长度依次为
3
,
3
,
1
,
2
,
2
,
2
,
4
,
4
,
4
,
4
,
4
,
4
3,3,1,2,2,2,4,4,4,4,4,4
3,3,1,2,2,2,4,4,4,4,4,4,和为
37
37
37。
数据范围与提示
对于
30
%
30\%
30% 的数据
N
≤
300
N≤300
N≤300。
对于
70
%
70\%
70% 的数据
N
≤
3000
N≤3000
N≤3000。
对于
100
%
100\%
100% 的数据对于所有输入的整数均不大于
1
0
5
10^5
105,输入的树保证连通,无重边,无自环。
题解
当去掉一条边,整棵树会被分割为两个连通块 A , B A,B A,B。这条边被经过的次数就是:
A A A的叶子节点数* B B B的节点数+ A A A的节点数* B B B的叶子节点数
乘上边长就是这条边的总贡献值。
这样我们dfs搜每个点,求出包括它自己的它子树的节点数和叶子节点数,又知道了总的节点数和叶子节点数,就可以求得这个点与它父节点之间道路的贡献值了。
这题似乎还有树形dp的做法(毕竟在oj上标签有这个),如果我知道了会补充(咕咕咕)。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct node{
long long nd,lve;
}nodes[100005];
struct rd{
long long des,len;
}now;
vector <rd> rds[100005];
long long n,m,l,b,c,lves,ans,fadis[100005],cs;
void dfs(int p,int come){
nodes[p].nd=1;
if(rds[p].size()==1&&rds[p][0].des==come){
nodes[p].lve=1;
lves++;
return;
}
for(int i=0;i<rds[p].size();i++){
if(rds[p][i].des==come) continue;
dfs(rds[p][i].des,p);
fadis[rds[p][i].des]=rds[p][i].len;
nodes[p].nd+=nodes[rds[p][i].des].nd;
nodes[p].lve+=nodes[rds[p][i].des].lve;
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld",&l,&b,&c);
if(b<c) swap(b,c);
now.des=b;
now.len=l;
rds[c].push_back(now);
now.des=c;
rds[b].push_back(now);
}
dfs(1,0);
for(int i=1;i<=n;i++){
cs=(n-nodes[i].nd)*nodes[i].lve+(lves-nodes[i].lve)*nodes[i].nd;
ans+=fadis[i]*cs;
}
printf("%lld\n",ans);
return 0;
}