[关闭]
@WangYixu 2018-06-15T11:30:32.000000Z 字数 842 阅读 787

[NOIP2014]联合权值

OI 题解

算法:dfs

代码解析:

数据结构

  1. ll v[N];
  2. ll head[N], next[M], to[M], cnt;
  3. ll n;
  4. ll ans, mx;
  5. inline void adde(int x, int y) {
  6. ++cnt;
  7. to[cnt] = y;
  8. next[cnt] = head[x];
  9. head[x] = cnt;
  10. }

主函数

  1. int main() {
  2. scanf("%d", &n);
  3. for(int i = 1, x, y; i < n; ++i) {
  4. scanf("%d %d", &x, &y);
  5. adde(x, y);
  6. adde(y, x);
  7. }
  8. for(int i = 1; i <= n; ++i) {
  9. scanf("%lld", &v[i]);
  10. }
  11. dfs(1, 0, 0);
  12. printf("%lld %lld", mx, (ans * 2) % 10007);
  13. return 0;
  14. }

关键:dfs

  1. void dfs(int x, int fa, int grfa) {
  2. ans += v[x] * v[grfa];
  3. mx = max(mx, v[x] * v[grfa]);
  4. /*直接循环判断太慢
  5. * for(int i = head[x]; i; i = next[i]) if(to[i] != fa) {
  6. * for(int j = next[i]; j; j = next[j]) if(to[j] != fa) {
  7. * ans += v[to[i]] * v[to[j]];
  8. * mx = max(mx, v[to[i]] * v[to[j]]);
  9. * }
  10. * dfs(to[i], x, fa);
  11. * }
  12. */
  13. ll bsum = 0, bmx = 0;
  14. for(int i = head[x]; i; i = next[i]) if(to[i] != fa) {
  15. ans += v[to[i]] * bsum;
  16. mx = max(mx, v[to[i]] * bmx);
  17. bsum += v[to[i]];
  18. bmx = max(v[to[i]], bmx);
  19. dfs(to[i], x, fa);
  20. }
  21. }

注意到一开始使用的二重循环,复杂度高达,实在是太naive了。
观察到如果固定了j,就相当于枚举每个在j之前的i,于是就利用了前缀和的思想进行优化,复杂度降低到

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注