码迷,mamicode.com
首页 > 其他好文 > 详细

[noip2014] 联合权值

时间:2019-10-29 19:44:07      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:style   col   通过   ios   bsp   pac   处理   产生   ret   

传送门

讲一下题意:

有n个节点,n-1条边,无重边无子环(这不就是一棵树吗)。每两条边的权值为1,每个点有一个值W,对于有序点对(u, v)满足u到v之间的距离为2,就会产生一个联合权值Wu * Wv。求∑Wu* Wv 和max{Wu * Wv}。

 这道题刚开始看上去很怪异,就想着求一下深度再求一下LCA然后枚举每个满足条件的点对。不过后来我发现这是一棵树,两个点之间的距离为2的话只有一种可能:

A -- B -- C

(A, C)是有序点对。

所以我们只需要枚举中转点(B),然后对于每一个中转点会产生∑

很明显,这两个值都可以通过前缀和预处理出来。

之后对于每个中转点再预处理一个最大值个一个次大值得MAX = max{最大值 * 次大值}。

#include <iostream>
using namespace std;
const int MOD = 10007, N = 200010;
struct node{
    int pre, to;
}edge[2 * N];
int head[N], tot;
int s1[N], s2[N], ma1[N], ma2[N];
int n, maxi, sum;
int x[N], y[N], w[N];
void add(int u, int v) {
    //存边,预处理 
    edge[++tot] = node{head[u], v};
    head[u] = tot;
    s1[u] = (s1[u] + w[v]) % MOD;
    s2[u] = (s2[u] + w[v] * w[v]) % MOD;
    if (w[v] > ma1[u]) {
        ma2[u] = ma1[u];
        ma1[u] = w[v];
    } else if (w[v] > ma2[u]) {
        ma2[u] = w[v];
    }
}
int main() {
    cin >> n;
    for (int i = 1; i < n; i++) cin >> x[i] >> y[i];
    for (int i = 1; i <= n; i++) cin >> w[i];
    for (int i = 1; i < n; i++) add(x[i], y[i]), add(y[i], x[i]);
    for (int pos = 1; pos <= n; pos++) {
        sum = (sum + s1[pos] * s1[pos] - s2[pos]) % MOD;//注意要取模 
        maxi = max(maxi, ma1[pos] * ma2[pos]);
    }
    cout << maxi << " " << sum << endl;
    return 0;
}

 

[noip2014] 联合权值

标签:style   col   通过   ios   bsp   pac   处理   产生   ret   

原文地址:https://www.cnblogs.com/zcr-blog/p/11760903.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!