搜索场 day1 A 求和

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的正整数。

#include<cstdio>
#include<cstring>
#define ll long long 
using namespace std;
const int N=100010;
struct node
{
    int next,to,p;
}e[N*2];
int first[N],book[N],size[N];
int cnt=0;
ll sum=0;
int n;

void insert(int v,int u,int p)
{
    e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].p=p;
    e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;e[cnt].p=p;
}

void dfs1(int x)
{
    book[x]=1;size[x]=1;
    for(int i=first[x];i;i=e[i].next)
    {
        if(book[e[i].to]==0)
        {
            dfs1(e[i].to);
            size[x]+=size[e[i].to];
        }
    }
}

void dfs(int x)
{
    book[x]=1;
    for(int i=first[x];i;i=e[i].next)
    {
        if(book[e[i].to]==0)
        {
            sum+=(ll)e[i].p*size[e[i].to]*(n-size[e[i].to]);
            dfs(e[i].to);
        }
    }
}

int main()
{
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    scanf("%d",&n);
    int v,u,p;
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d %d %d",&u,&v,&p);
        insert(u,v,p);
    }
    memset(book,0,sizeof(book));
    dfs1(1);
    memset(book,0,sizeof(book));
    dfs(1);
    printf("%lld
",sum);
}
View Code

 谢谢师兄(czl)教导。

原文地址:https://www.cnblogs.com/12fs/p/7349613.html