统计损失

统计损失
题目描述
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国将受到的损失之和。
样例输入
5
7 6 6 1 1 
1 2
2 3
2 4
1 5
样例输出
778
提示
n<=100;
n<=3000;

n<=100000;


n<=3000时 

   可以n^2,遍历每一条边,轻松愉快。

统计损失_第1张图片

n<=100000时 

   树形DP

   很明显,只要搜一遍,再把子树两两相乘在加上本身。

   两两相乘可以用数学方法计算

#include 
#include
#include
#include
#include
#include
using namespace std;
#define maxn 100086
#define Mod 10086;
struct node
{
    int next,to;
}edge[maxn*2];
int head[maxn],num,val[maxn],f[maxn],ans;
bool visit[maxn];
void add(int from,int to)
{
    edge[++num].next=head[from];
    edge[num].to=to;
    head[from]=num;
}
void dfs(int now)
{
    long long tmp=0,temp=0;
    visit[now]=true;
    for(int i=head[now];i!=0;i=edge[i].next)
        if(!visit[edge[i].to])
        {
            dfs(edge[i].to);
            tmp+=f[edge[i].to];
            temp+=f[edge[i].to]*f[edge[i].to];
        }
    f[now]=((tmp+1)*val[now])%Mod;
    tmp=tmp*tmp;
    tmp=(tmp-temp)/2;
    tmp%=Mod;
    tmp=(tmp*val[now])%Mod;
    ans=(ans+f[now]+tmp)%Mod; 
}
int main()
{
    num=0;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&val[i]);
        val[i]%=Mod;
    }
    for(int i=1;i




你可能感兴趣的:(树形DP)