NOIP2014 联合权值

题目链接

https://www.luogu.org/problemnew/show/P1351

 

这道题40分钟AC掉了,不算快

但是我WA了三次……

考试的时候只能交一次……

 

首先我看到样例就给误导了,以为距离为2的路径只有儿子到爷爷这一段

然后分分钟敲好,加上去WA

然后仔细想了想,貌似还有一种情况,就是一个父亲的两个儿子

写完后交,又WA

发现有的地方没有取模,爆int……

最后该取模的地方还没有发现完全,交上去WA

最后想到统计权值和的时候要取模

终于AC……

 

以前一般认为相乘的式子要取模

以后注意下一下多个数求和也要注意……

还有就是要想周全

 

不过之后对比一下自己和别人的代码还是学到很多的

总结

(1)爷爷的求法可以放到dfs里面作为一个参数,下一层是dfs(v, u, fa)
(2)对于求和的部分卡了一下。对于每个点,权值有(sum-w[u])*w[u]

可以写个for算一遍

不过这个for可以省去

拆开后就是sum * w[u] - w[u] * w[u]

 所有的u加起来就是

sum * (w[u1] + w[u2]……) - w[u1] - w[u2]……

sum * sum- w[u1] - w[u2]……

所以记录一下w[u1] * w[u1] + w[u2] * w[u2]……就好了

(3)注意看每一个地方会不会爆int,要取模

(4)思维要周全

(5)维护最大值和次大值的写法要写对

#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;

const int MAXN = 2e5 + 10;
const int MOD = 10007;

struct Edge{ int to, next; };
Edge e[MAXN << 1];
int head[MAXN], tot;
int w[MAXN], n, m, ans, maxt; 

void AddEdge(int from, int to)
{
    e[tot] = Edge{to, head[from]};
    head[from] = tot++;
}

void read(int& x)
{
    int f = 1; x = 0; char ch = getchar();
    while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
    while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    x *= f;
}

void dfs(int u, int fa, int g)
{
    int max1 = 0, max2 = 0, sum = 0, t = 0;
    for(int i = head[u]; ~i; i = e[i].next)
    {
        int v = e[i].to;
        if(v == fa) continue;
        dfs(v, u, fa);
        
        t = (t + w[v] * w[v]) % MOD;
        sum = (sum + w[v]) % MOD;
        if(w[v] > max1) { max2 = max1, max1 = w[v]; }
        else if(w[v] > max2) max2 = w[v];
    }
    
    maxt = max(maxt, max(w[u] * w[g], max1 * max2));
    ans = (ans + w[u] * w[g] * 2 % MOD + (sum * sum % MOD - t + MOD)) % MOD;
}

int main()
{
    memset(head, -1, sizeof(head)); tot = 0;
    scanf("%d", &n);
    REP(i, 1, n)
    {
        int u, v; read(u); read(v);
        AddEdge(u, v); AddEdge(v, u);
    }
    _for(i, 1, n) read(w[i]);
    
    dfs(1, 0, 0);
    printf("%d %d\n", maxt, ans);
    
    return 0;
}

 

posted @ 2018-10-30 12:48  Sugewud  阅读(144)  评论(0)    收藏  举报