NOIP2014 联合权值 解题报告(乱搞(据说这道题是树状dp,感觉好像是))

来源:互联网 发布:js和jquery中的event 编辑:程序博客网 时间:2024/05/16 10:07

在线评测:

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;
}

0 0