NOIP 提高组 2014 联合权值(图论???)

传送门

https://www.cnblogs.com/violet-acmer/p/9937201.html

 

题解:

  相关变量解释:

int n;
int fa[maxn];//fa[i] : i的父亲节点
int w[maxn];//w[i] : i的权值
long long sum[maxn];//sum[i] : i节点的所有儿子节点的权值和
int maxSon1[maxn];//maxSon1[i] : i节点的所有儿子中权值最大值(如果有超过两个儿子)
int maxSon2[maxn];//maxSon2[i] : i节点的所有儿子中权值第二大值(如果有超过两个儿子)
vector<int >G[maxn];//存边
vector<int >son[maxn];//son[i] : 记录节点 i 的所有儿子节点

  步骤:

  (1):先Dfs(u,f)预处理出节点u的父亲节点fa[u],儿子节点son[u],儿子节点的权值和sum[u],以及儿子节点的权值最大的前两个权值maxSon1[u],maxSon2[u];

  (2):如果某节点 i 含有两个及以上儿子,则每两个儿子间也可构成长度为 2 的边长,求出节点 i 的儿子节点的联合权值,并判断是否可以更新联合权值的最大值;

  (3):求 i 节点与其父亲的父亲节点 j 构成的联合权值,并将其二倍(i 与 j 构成联合权值,同样 j 与 i 也可以构成联合权值,所以需要加入两个)与加入到联合权值之和

       中,并判断是否可以更新联合权值的最大值。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back(x)
 4 #define mem(a,b) memset(a,b,sizeof(a))
 5 const int maxn=200000+10;
 6 const int MOD=10007;
 7 
 8 int n;
 9 int fa[maxn];
10 int w[maxn];
11 long long sum[maxn];
12 int maxSon1[maxn];
13 int maxSon2[maxn];
14 vector<int >G[maxn];
15 vector<int >son[maxn];
16 void addEdge(int u,int v)
17 {
18     G[u].pb(v);
19     G[v].pb(u);
20 }
21 void Dfs(int u,int f)
22 {
23     fa[u]=f;
24     for(int i=0;i < G[u].size();++i)
25     {
26         int to=G[u][i];
27         if(to != f)
28         {
29             son[u].pb(to);
30             sum[u] += w[to];
31             if(w[to] > maxSon1[u])
32             {
33                 if(maxSon1[u] > maxSon2[u])
34                     maxSon2[u]=maxSon1[u];
35                 maxSon1[u]=w[to];
36             }
37             else if(w[to] > maxSon2[u])
38                 maxSon2[u]=w[to];
39             Dfs(to,u);
40         }
41     }
42 }
43 
44 void Solve()
45 {
46     mem(sum,0);
47     mem(maxSon1,0);
48     mem(maxSon2,0);
49     Dfs(1,-1);
50     int maxRes=0;
51     int res=0;
52     for(int i=1;i <= n;++i)//步骤(2)
53     {
54         if(son[i].size() >= 2)
55         {
56             maxRes=max(maxRes,maxSon1[i]*maxSon2[i]);
57             for(int j=0;j < son[i].size();++j)
58                 res=res%MOD+((sum[i]-w[son[i][j]])%MOD)*(w[son[i][j]]%MOD);
59         }
60     }
61     for(int i=2;i <= n;++i)//步骤(1)
62     {
63         if(fa[i] != 1)
64         {
65             maxRes=max(maxRes,w[fa[fa[i]]]*w[i]);
66             res=res%MOD+2*w[fa[fa[i]]]*w[i];
67         }
68     }
69     printf("%d %d\n",maxRes,res%MOD);
70 }
71 int main()
72 {
73     scanf("%d",&n);
74     for(int i=1;i < n;++i)
75     {
76         int u,v;
77         scanf("%d%d",&u,&v);
78         addEdge(u,v);
79     }
80     for(int i=1;i <= n;++i)
81         scanf("%d",w+i);
82     Solve();
83 }
View Code

  坑:  

    步骤(2)的情况刚开始忘了,然后,吃了一发wa.................

posted @ 2018-11-09 22:08  HHHyacinth  阅读(170)  评论(0编辑  收藏  举报