统计损失
【问题描述】
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\n",ans);
return 0;
}