【NOIP2014 联合权值】

#include <cstdio>
#include <climits>

const int MAXN = 200000 + 5;
int MOD = 10007;

struct Node;
struct Edge;

struct Node {
    int w;
    Edge *lastE;
}N[MAXN];

struct Edge {
    Node *from, *to;
    Edge *next;

    Edge (Node *from, Node *to) : from(from), to(to), next(from->lastE) {}
};

void AddEdge(int u, int v)
{
    N[u].lastE = new Edge(&N[u], &N[v]);
    N[v].lastE = new Edge(&N[v], &N[u]);
}

int n;
long long ans;

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        AddEdge(u, v);
    }

    for (int i = 1; i <= n; i++) scanf("%d", &N[i].w);

    int MAX = INT_MIN;

    for (int i = 1; i <= n; i++)
    {
        long long m = 0; //定义在函数内的变量要记得赋初值
        int MAXm = 0, MINm = 0;

        for (Edge *e = N[i].lastE; e; e = e->next)
        {
            if (e->to->w >= MAXm){
                MINm = MAXm;
                MAXm = e->to->w;
            }
            else if (e->to->w >= MINm)
                MINm = e->to->w;  //这点没想到,这个点有可能是虽然不是最大的,但是是次大的
            m += e->to->w; //这里m有可能爆int,所以要用long long
        }

        for (Edge *e = N[i].lastE; e; e = e->next)
        {
            (ans += ((m - e->to->w) * e->to->w) % MOD) %= MOD;
        }

        if (MAXm * MINm > MAX)
        {
            MAX = MAXm * MINm;
        }
    }

    printf("%d %lld\n", MAX, ans);
    return 0;
}

代码是Sulfur6_L8972帮忙debug过的。
方法是Rachel教的。
就是一个点,以它为中心,周围所有点的联合权值之和为每一个互相相乘。例如有四个点A、B、C、D,和就为     A*B+A*C+A*D+B*A+B*C+B*D+C*A+C*B+C*D+D*A+D*B+D*C
= A(B+C+D)+B(A+C+D)+C(A+B+D)+D(A+C+D)
=A(m-A)+B(m-B)+C(m-C)+D(m-D).
但是教了方法我也懂了之后还是没能调出来,就是我的细节的锅了。不过感觉最近做了些题,积累了一些常见的错误及调试方法,也算有些收获。

主要的bug都在程序里注释出来了,另外还要注意主函数里的变量在哪里需要被重新定义,它的范围到哪里。

Sulfur6_L8972说也可以把m += e->to->w;改成m = (m + e->to->w) % MOD;但是模出来有可能是负的,需要在最后在加上啥啥啥再模一遍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值