zoukankan      html  css  js  c++  java
  • P1351 联合权值

    联合权值

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

    洛谷链接

    这道题是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
  • 相关阅读:
    k8s令牌登录设置方法
    etcd查看集群信息
    go Map
    go 切片重组
    go For-range结构
    go 切片
    go 数组与切片
    go 内存优化
    go 格式化输出
    go 闭包函数
  • 原文地址:https://www.cnblogs.com/jsawz/p/6811374.html
Copyright © 2011-2022 走看看