联合权值——树上问题2014noip

联合权值

题面

思路

枚举每一个点作为中间节点

计算出它所有儿子y的权值和sum

每个儿子的要和其他儿子算一遍联合权值,

所以是\(w[y] * (sum - w[y])\)

最大值的话顺便记录下来就行

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 400000;
int ne[N], ver[N], idx, head[N];
long long ans;
long long sum;
long long a[N];
int n;
long long res;
const int mod = 10007;
void add(int u, int v) {
  ne[idx] = head[u];
  ver[idx] = v;
  head[u] = idx;
  idx++;
}

void dfs(int x) {
  long long t1 = 0, t2 = 0;
  sum = 0;
  for (int i = head[x]; i != -1; i = ne[i]) {
    int j = ver[i];
    sum = ((sum + a[j]) + mod) % mod;
    if (a[j] > t1) {
      t2 = t1;
      t1 = a[j];
    } else if (a[j] > t2) {
      t2 = a[j];
    }
  }
  ans = max(ans, (long long)t2* t1 );
  for (int i = head[x]; i != -1; i = ne[i]) {
    int j = ver[i];
    res = (res + ((long long)(sum - a[j]) * a[j] % mod) + mod) % mod;
  }
}
int main() {
  memset(head, -1, sizeof(head));
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    add(a, b);
    add(b, a);
  }
  for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
  for (int i = 1; i <= n; i++) {
    dfs(i);
  }
  cout <<ans << ' ' << (res + mod) % mod << endl;
  return 0;
}

注意:

前一个答案不用取模,要看清楚题面

posted @ 2020-12-03 09:46  邦的轩辕  阅读(66)  评论(0编辑  收藏  举报