【NOIP2014】联合权值 乱搞

【NOIP2014】联合权值 乱搞_第1张图片

【NOIP2014】联合权值 乱搞_第2张图片

只有图QAQ

距离为2,边权为1,所以和同一个点相连的其它点之间都会产生联合权值,枚举60分2333

可是我们为什么要枚举呢?

若当前和节点u相连的节点的权值是wi,此时u又新加了个节点m,权值为wx,那么:

ans1为最大值,ans2为总和
ans1=max(ans1,max{wi}*wx);
ans2=ans2+w1*wx+w2*wx+...wn*wx=ans2+∑wi*wx

我们发现,只要记录当前节点所连的点的历史最大值和历史权值之和,就可以O(1)来更新两个答案了。

不过要注意,ans2对于一组关系只计算了一次,别忘了乘2 。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int size=300010;
const int mod=10007;
int f[size],t[size];
int value[size];
int sum[size],maxn[size];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&f[i],&t[i]);
    }

    for(int i=1;i<=n;i++) scanf("%d",&value[i]);

    int ans1=0,ans2=0;
    for(int i=1;i<=n-1;i++)
    {
        ans1=max(ans1,max(value[f[i]]*maxn[t[i]],value[t[i]]*maxn[f[i]]));
        ans2=(ans2%mod+((value[f[i]]%mod)*(sum[t[i]]%mod))%mod+((value[t[i]]%mod)*(sum[f[i]]%mod))%mod)%mod;
        sum[f[i]]+=value[t[i]];
        sum[t[i]]+=value[f[i]];
        maxn[f[i]]=max(maxn[f[i]],value[t[i]]);
        maxn[t[i]]=max(maxn[t[i]],value[f[i]]);
    }
    printf("%d %d",ans1,(ans2*2)%mod);
    return 0;
}
/* 5 1 2 2 3 3 4 4 5 1 5 2 3 10 g++ 联合权值std.cpp -o 联合权值std.exe -Wall */

你可能感兴趣的:(NOIP2014)