联合权值dp

        联合权值

                洛谷中可找到

 


题目传送门https://www.luogu.org/problemnew/show/P1351

这题我就得了70分(TLE)  GG了

就是遍历它孩子的孩子(爷爷和孙子),然后相乘;

ps:这样会有很多重复,TLE

 1 #include<cstdio>
 2 #include<iostream>
 3 #define maxn 200000+10
 4 using namespace std;
 5 int max(int x,int y)
 6 {
 7     return x>y?x:y;
 8 }
 9 int n;
10 struct ii{
11     int u,v,nxt;
12 }a[maxn*2];
13 int w[maxn];
14 int head[maxn];
15 int o;
16 inline void add(int x,int y)
17 {
18     a[++o].u=x;
19     a[o].v=y;
20     a[o].nxt=head[x];
21     head[x]=o;    
22 }
23 int main()
24 {
25 //    freopen("link.in","r",stdin);
26 //    freopen("link".out,"w",stdout);
27     scanf("%d",&n);
28     for(int i=1,x,y;i<n;++i)
29     {
30         scanf("%d%d",&x,&y);
31         add(x,y);
32         add(y,x);
33     }
34     for(int i=1;i<=n;++i)
35         scanf("%d",&w[i]);
36     int jl=0;
37     int zui=0,he=0,wkk=0;
38     for(int i=1;i<=n;++i)
39     {
40         for(int j=head[i];j;j=a[j].nxt)
41         {
42             for(int zz=head[a[j].v];zz;zz=a[zz].nxt)
43             {
44                 if(a[zz].v!=i)
45                 {
46                     wkk=w[a[zz].v]*w[i];
47                     zui=max(zui,wkk);
48                     he+=wkk;
49                     he%=10007;
50                 }
51             } 
52         }
53     }
54     printf("%d %d",zui,he);
55     return 0;
56 }
View Code

 


 


正解

#include<iostream>
#include<cstdio>
#define maxn 300000+10
using namespace std;
int n;
int max(int x,int y)
{
    return x>y?x:y;
}//手写max,fast 

struct ii{
    int v,nxt; 
}a[1000000];//链式强向星存图1 
int head[300000];
int w[300000];
int he,ma;//ans 

int o;//存图 
void add(int x,int y)
{
    a[++o].v=y;
    a[o].nxt=head[x];
    head[x]=o;
}

int main()
{
     cin>>n;
     int x,y;
     for(int i=1;i<=n-1;++i)
     {
         scanf("%d%d",&x,&y);//输入 
         add(x,y);add(y,x);//正反存一遍 
    }
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&w[i]);//输入价值 
    }
    int sum,zui;//sum是孩子加起来的和,zui是孩子中最大的 
    for(int i=1;i<=n;++i)
    {
        sum=(zui=w[a[head[i]].v])%10007;//初始值 
        for(int j=a[head[i]].nxt;j;j=a[j].nxt)//从第二个孩子开始遍历 
        {
            //这一部分是求和 
            he=(he+sum*w[a[j].v])%10007;//乘法结合律 
            sum=(sum+w[a[j].v])%10007;//更新孩子和 
            //这一部分是求最大值 
            ma=max(ma,zui*w[a[j].v]);//更新最大值 
            zui=max(zui,w[a[j].v]);//更新孩子中的最大值
            //因为这是最后更新的,所以不用担心出现最大值和自己相乘 
        }
    }
        



    printf("%d %d",ma,he*2%10007);//别忘了he*2 
     return 0;
} 

 

posted @ 2018-04-21 20:42  ComplexPug  阅读(179)  评论(0编辑  收藏  举报