• [NOIP2014]联合权值 题解


    题目大意:

      有一棵树,求距离为2的点权的乘积的和以及最大值。

    思路:

      枚举每一个点,则与其相邻的点互为距离为2的点。该部分的最大值为点权最大的两个点的积,和为点的权值和的平方减去每个点的平方,这样每条边都被跑了两次,所以复杂度为O(n)。

      用邻接表存储要开双倍数组(无向),当然像cyk大神一样直接跑边就不用考虑这个了。

    代码:

      邻接表:

     1 #include<cstdio>
     2 const int mo=10007,M=200008;
     3 int cnt,x,y,n,i,ans,tot,w[M],v[M<<1],last[M<<1],head[M<<1];
     4 
     5 void add(int x,int y) { v[++cnt]=y,last[cnt]=head[x],head[x]=cnt; }
     6 
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     for (i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    11     for (i=1;i<=n;i++) scanf("%d",&w[i]);
    12     for (i=1;i<=n;i++)
    13     {
    14         int sum=0,max1=0,max2=0,j,o;
    15         for (j=head[i];j;j=last[j])
    16         {
    17             o=w[v[j]];
    18             sum=(sum+o)%mo;
    19             if (o>max1) max2=max1,max1=o;
    20             else if (o>max2) max2=o;
    21             tot=(tot-o*o)%mo;
    22         }
    23         tot=(tot+sum*sum)%mo;
    24         sum=max1*max2;
    25         if (sum>ans) ans=sum;
    26     }
    27     printf("%d %d
    ",ans,tot);
    28     return 0;
    29 }

      %%%cyk大神:

     1 #include<iostream>
     2 using namespace std;
     3 int i,n,maxx,ans,x[200005],y[200005],w[200005];
     4 int am[200005],am2[200005],s[200005],qs[200005];
     5 int main()
     6 {
     7     cin>>n;
     8     for (i=1;i<=n-1;i++) cin>>x[i]>>y[i];
     9     for (i=1;i<=n;i++) cin>>w[i];
    10     for (i=1;i<=n-1;i++)
    11       {
    12           s[x[i]]=(s[x[i]]+w[y[i]])%10007;
    13           qs[x[i]]=(qs[x[i]]+w[y[i]]*w[y[i]])%10007;
    14           s[y[i]]=(s[y[i]]+w[x[i]])%10007;
    15           qs[y[i]]=(qs[y[i]]+w[x[i]]*w[x[i]])%10007;
    16           if (w[y[i]]>am[x[i]]) {am2[x[i]]=am[x[i]];am[x[i]]=w[y[i]];}
    17           else if (w[y[i]]>am2[x[i]]) am2[x[i]]=w[y[i]];
    18           if (w[x[i]]>am[y[i]]) {am2[y[i]]=am[y[i]];am[y[i]]=w[x[i]];}
    19           else if (w[x[i]]>am2[y[i]]) am2[y[i]]=w[x[i]];
    20       }
    21     maxx=0;
    22     for (i=1;i<=n;i++) maxx=max(maxx,am[i]*am2[i]);
    23     ans=0;
    24     for (i=1;i<=n;i++) ans=(ans+s[i]*s[i]-qs[i])%10007;
    25     cout<<maxx<<' '<<ans;
    26 }
  • 相关阅读:
    设计模式--4建造者模式
    java中的方法重载与重写以及方法修饰符
    设计模式--3.模板方法模式
    设计模式--2.工厂方法模式
    设计模式--1.单例模式
    问题--时景某些用户不能发表评论解决方案
    EXCEL:从一组数据中查找我想要的某个数据是否存在
    Git版本控制--05--可以吃后悔药之版本回退
    Git版本控制--04--文件修改后怎么提交
    Git版本控制--03--怎么向Git仓库中添加文件
  • 原文地址:https://www.cnblogs.com/HHshy/p/6056168.html
Copyright © 2020-2023  润新知