路上路径求和

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;
}
View Code
原文地址:https://www.cnblogs.com/lyzuikeai/p/7343811.html