码迷,mamicode.com
首页 > 其他好文 > 详细

P1351 联合权值

时间:2017-05-05 10:45:31      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:stream   ora   image   line   text   可以转化   更新   int   als   

联合权值

然而这只是一道普及+/提高的大水题

洛谷链接

这道题是2014年提高组day1的第二题。

简单题意就是在树上每个点都有权值,相邻两点的距离为1,求距离为2的点的权值乘积的和以及最大值。

基本思路就是遍历整棵树,然后找到距离该点距离为2的点,计算距离,更新最大值和乘积和。

但这样就很慢了。所以我们可以遍历中间点,然后找到中间所连接的点,计算他们两两之间的乘积。

 技术分享

以上图为例:

先找到节点1,遍历与1相连的节点,有2,3,4。

计算与2距离为2的节点,有3,4。所以乘积和为dis[2]*(dis[3]+dis[4])。

计算与3距离为2的节点,有2,4。所以乘积和为dis[3]*(dis[2]+dis[4])。

计算与4距离为2的节点,有2,3。所以乘积和为dis[4]*(dis[2]+dis[3])。

这样计算还是比较麻烦,怎么简化呢?

我们可以通过转化式子来达到此目的。

dis[2]*(dis[3]+dis[4])就可以转化成dis[2]*dis(dis[2]+dis[3]+dis[4])-dis[2]^2。

dis[3]*(dis[2]+dis[4])就可以转化成dis[3]*dis(dis[2]+dis[3]+dis[4])-dis[3]^2。

dis[4]*(dis[2]+dis[3])就可以转化成dis[4]*dis(dis[2]+dis[3]+dis[4])-dis[4]^2。

 把他们放到一起,就是(dis[2]+dis[3]+dis[4])^2-dis[2]^2-dis[3]^2-dis[4]^2。

也就是点1连接的所有点的权值和的平方减去平方和,就可以计算出答案了。

技术分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #define N 1000000
 4 #define M 200010
 5 using namespace std;
 6 long long next[N],to[N],head[M],num,j,dis[M],ans1,ans2,ans,n,a,b,mmax=-1;
 7 void add(long long false_from,long long false_to){
 8     next[++num]=head[false_from];
 9     to[num]=false_to;
10     head[false_from]=num;
11 }
12 void dfs(long long x){
13     ans1=0;
14     ans2=0;
15     long long k=1,mmax1=-1,mmax2=-1;
16     for(long long i=head[x];i;i=next[i]){
17         j=next[i];
18         if(i==head[x]&&!j){
19             k=0;
20             break;
21         }
22         if(dis[to[i]]>mmax1)
23             mmax1=dis[to[i]];
24         else
25             if(dis[to[i]]>mmax2)
26                 mmax2=dis[to[i]];
27         ans1+=dis[to[i]];
28         ans2+=dis[to[i]]*dis[to[i]];
29     }
30     if(k){
31         mmax=max(mmax,mmax1*mmax2);
32         ans+=ans1*ans1-ans2;
33         ans%=10007;
34     }
35 }
36 int main(){
37     scanf("%lld",&n);
38     for(long long i=1;i<n;++i){
39         scanf("%lld%lld",&a,&b);
40         add(a,b);
41         add(b,a);
42     }
43     for(long long i=1;i<=n;++i)
44         scanf("%lld",&dis[i]);
45     for(long long i=1;i<=n;++i)
46         dfs(i);
47     printf("%lld %lld",mmax,ans);
48     return 0;
49 }
View Code

 

P1351 联合权值

标签:stream   ora   image   line   text   可以转化   更新   int   als   

原文地址:http://www.cnblogs.com/jsawz/p/6811374.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!