在线评测:
http://codevs.cn/problem/3728/
整体思路:
首先我们认真阅读题意,发现这是一个树,这样子我们就可以加特技了!
我们在搜索一个点的时候,我们先把这个点所能连出的所有点的和加起来并记录,并记录这个点连出的最大值和次大值。同时我们去用他和他父节点记录的以上数值进行运算,将他父节点的记录的和减去这个点的权值,然后将权值与父节点的和相乘加入到结果中,并用父节点连出的最大值,或次大值(最大值为这个点本身)来更新全局最大值。在1号点时我们特判一下什么都不做就行。同时我们这样运算对于两个点,我们只计算了他俩联合一次,所以结果最后要乘2输出,
失误之处:
开始运算结果中间量的时候没有开long long 于是很悲催的炸了几个点,
体会心得:
注意数值范围!!!
AC代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;int n,w[300000],u,v,sum,maxn;int head[600000],nxt[600000],to[600000];int jlm[300000],jls[300000],jlh[300000],fa[300000];int jlwm[300000],f1;bool vis[300000];long long ans = 0;void cr(int x,int y){ sum++; nxt[sum] = head[x]; head[x] = sum; to[sum] = y;}void dfs(int x){ vis[x] = true; if (fa[x] == 1 && f1 == 1) { }else if (fa[x]) { jlh[fa[x]] -= w[x]; long long ftp = w[x],itp = jlh[fa[x]]; ans += ftp * itp; ans %= 10007; if (x != jlwm[fa[x]]) { maxn = max(maxn,w[x] * jlm[fa[x]]); }else { maxn = max(maxn,w[x] * jls[fa[x]]); } } for (int tp = head[x];tp;tp = nxt[tp]) { if (x == 1) f1++; if (jlm[x] < w[to[tp]]) { jlm[x] = w[to[tp]]; jlwm[x] = to[tp]; } jlh[x] += w[to[tp]]; } for (int tp = head[x];tp;tp = nxt[tp]) { if (jls[x] < w[to[tp]] && to[tp] != jlwm[x]) { jls[x] = w[to[tp]]; } } for (int tp = head[x];tp && !vis[to[tp]];tp = nxt[tp]) { fa[to[tp]] = x; dfs(to[tp]); }}int main(){ scanf("%d",&n); for (int i = 1;i <= n - 1;i++) { scanf("%d%d",&u,&v); cr(u,v); cr(v,u); } for (int i = 1;i <= n;i++) scanf("%d",&w[i]); dfs(1); printf("%d %lld\n",maxn,ans * 2 % 10007); return 0;} |

本文介绍了一种解决特定类型在线评测问题的方法,利用树形结构进行深度优先搜索,并通过动态规划优化计算过程。文章详细解释了算法思路,包括如何记录每个节点的权重和最大值等关键步骤。
)&spm=1001.2101.3001.5002&articleId=52494679&d=1&t=3&u=d2ee120811e244e08176163a86399e50)
547

被折叠的 条评论
为什么被折叠?



