题目链接
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 ", maxt, ans); return 0; }