A 求和
时间限制: 1 Sec 空间限制: 256 MB
输入输出文件名:A.in,A.out
题目描述
给出一棵以1为根的有n个节点的树,树上每条边都有其边权。
求所有点对之间的路径上的边权和的总和。
输入格式:
第一行为n
接下来n-1行,每行三个整数,分别表示一条边的两端点编号和边权。(编号为1..n)
输出格式:
输出一个数字表示总和
输入样例
4
1 2 10
2 3 10
1 4 20
输出样例
130
样例解释
1->2:10 , 1->3:20 , 1->4:20 , 2->3:10 , 2->4:30 , 3->4:40 , 总和为130。
数据范围
对于30%的数据,1<=n<=300
对于80%的数据,1<=n<=3000
对于100%的数据,1<=n<=100000,边权为<=100的正整数。
—————————————————————————————————————
这是道套路题QAQ
单独考虑每条路径就好了
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=1e5+7; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } LL ans,w; int vis[M],n,x,y,sz[M]; int first[M],cnt; struct node{int from,to,next;LL w;}e[M*2]; void ins(int a,int b,LL w){cnt++; e[cnt]=(node){a,b,first[a],w}; first[a]=cnt;} void insert(int a,int b,LL w){ins(a,b,w); ins(b,a,w);} void dfs(int x){ vis[x]=1; sz[x]=1; for(int i=first[x];i;i=e[i].next){ int now=e[i].to; if(!vis[now]){ dfs(now); sz[x]+=sz[now]; } } } int main() { n=read(); for(int i=1;i<n;i++) x=read(),y=read(),w=read(),insert(x,y,w); dfs(1); for(int i=1;i<=cnt;i+=2){ int x=sz[e[i].from]<sz[e[i].to]?e[i].from:e[i].to; ans=ans+(LL)sz[x]*(n-sz[x])*e[i].w; } printf("%lld ",ans); return 0; }