zoukankan      html  css  js  c++  java
  • [noip2014] 联合权值

    传送门

    讲一下题意:

    有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;
    }
  • 相关阅读:
    too many open files linux服务器 golang java
    fasthttp 文档手册
    syncer.go
    grpc.go
    stm.go
    session.go
    mutex.go
    [HTML5]label标签使用以及建议
    禁止使用finalize方法
    [支付宝]手机网站支付快速接入
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/11760903.html
Copyright © 2011-2022 走看看