统计损失

【问题描述】

SJY有一天被LLT紧急召去计算一些可能的损失。LLT元首管理的SHB国的交通形成了一棵树,现在将会出现一颗陨石砸在SHB国中,并且陨石砸毁的必定是SHB国构成的交通树上的一条路径。SHB国的损失可表示为被砸毁的路径上的所有城市价值之积。现在还暂时无法确定陨石的掉落路线,所以LLT元首希望SJY能够告诉他SHB国在受到每一种砸毁方式后会受到的损失之和模10086之后的值。注意:单独一个节点也被认为是合法的路径。

【输入】

第1行一个数n,表示城市数。
第2行n个数,第i个数表示第i个城市的价值。
第3到n+1行,每行两个数u,v,表示城市u,v之间有一条道路。

【输出】

包含一个数,表示SHB国将受到的损失之和。

【输入输出样例】

count.in
5
7 6 6 1 1
1 2
2 3
2 4
1 5
count.out
778

【数据规模和约定】

对于20%的数据,n<=100;
对于50%的数据,n<=3000;
对于100%的数据,n<=100000。

【题解】

这里写图片描述

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define fp(i,a,b) for(int i=a;i<=b;i++)
#define fq(i,a,b) for(int i=a;i>=b;i--)
#define il inline
#define ll long long 
using namespace std;
const int MAX=100005;
const int mod=10086;
struct edge{int to,next;}a[MAX<<1];
int head[MAX],cnt;
int n,h[MAX],f[MAX],g[MAX],ans;
il int gi()
{
   int x=0;
   short int t=1;
   char ch=getchar();
  while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  if(ch=='-') t=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  return x*t;
}
void Add(int u,int v)
{
    a[++cnt]=(edge){v,head[u]};
    head[u]=cnt;
}
void dfs(int u,int fa)
{
    f[u]=h[u];g[u]=0;
    for(int e=head[u];e;e=a[e].next)
    {
        int v=a[e].to;
        if (v==fa) continue;
        dfs(v,u);
        f[u]=(f[u]+1ll*f[v]*h[u])%mod;
        ans=(ans+1ll*f[v]*h[u]*g[u])%mod;
        g[u]=(g[u]+f[v])%mod;
    }
    ans=(ans+f[u])%mod;
}
int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    n=gi();
    for (int i=1;i<=n;i++) h[i]=gi()%mod;
    for (int i=1;i<n;i++)
    {
        int u=gi(),v=gi();
        Add(u,v);Add(v,u);
    }
    dfs(1,0);
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/yanshannan/p/7413144.html