【NOIP2014】联合权值 乱搞

这里写图片描述
这里写图片描述
这里写图片描述


只有图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 
*/

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值