zoukankan      html  css  js  c++  java
  • 【NOIP2014提高组】联合权值

    https://www.luogu.org/problem/show?pid=1351

    既然是一棵树,就先转化成有根树。有根树上距离为2的点对,路径可能长下面这样:

    枚举路径上的中间点X。

     

    第一种情况

    对于点X(X的儿子数≥2),它的每一个儿子i与其他的儿子对权值和的贡献为Wi*(sum-Wi),则这个点所有儿子之间对权值和的贡献为:∑Wi*(sum-Wi),其中sum为点X所有儿子的权值之和。(貌似还有更高效的算法?)

    对于点X (X的儿子数≥2),它的所有儿子之间可以产生的联合权值的最大值,肯定为所有儿子里面权值最大的×权值第二大的。贪心即可。

    第二种情况

    对于点X(除根节点和叶子节点),它的父亲与它的所有儿子之间对权值和的总贡献为:2*Wfather*sum,其中sum为点X所有儿子的权值之和。因为要求的是有序点对,所以要乘2。

    对于点X(除根节点和叶子节点),它的父亲与它的所有儿子之间产生的联合权值的最大值,肯定为它的儿子里面权值最大的乘以它的父亲的权值。贪心即可。

    实际代码时发现不用特意转化为有根树,只需要一遍深搜。

    对于每个点,判断它的儿子数时,如果不是根则等于这个点的度数-1,如果是根则等于这个点的度数。

    统计每个点对权值和的贡献,并维护最大权值。

    #include <iostream>
    #include <vector>
    #define maxn 200005
    typedef long long llint;
    using namespace std;
    const llint inf = 0x7fffffffffffffffll, c = 10007;
    int n;
    vector<int> t[maxn];
    llint weight[maxn];
    llint tot = 0;
    llint maxlink = -inf;
    void dfs(int k, int fa)
    {
        llint sum = 0;
        llint maxson[2] = {-inf, -inf};
        for (int i = 0; i < t[k].size(); i++)
        {
            if (t[k][i] != fa)
            {
                sum = (sum + weight[t[k][i]]) % c;
                if (weight[t[k][i]] > maxson[0])
                {
                    maxson[1] = maxson[0];
                    maxson[0] = weight[t[k][i]];
                }
                else if (weight[t[k][i]] > maxson[1])
                {
                    maxson[1] = weight[t[k][i]];
                }
                dfs(t[k][i], k);
            }
        }
        if (t[k].size() >= 2 + (fa != 0 ? 1 : 0))
        {
            for (int i = 0; i < t[k].size(); i++)
                if (t[k][i] != fa)
                    tot = (tot + (sum - weight[t[k][i]] + c) % c * weight[t[k][i]] % c) % c;
            // tot = tot + (sum - weight[t[k][i]]) * weight[t[k][i]]
            maxlink = max(maxlink, maxson[0] * maxson[1]);
        }
        if (fa != 0 && t[k].size() >= 2)
        {
            tot = (tot + 2 * weight[fa] % c * sum % c) % c;
            maxlink = max(maxlink, maxson[0] * weight[fa]);
        }
    }
    int main()
    {
        int a, b;
        cin >> n;
        for (int i = 1; i < n; i++)
        {
            cin >> a >> b;
            t[a].push_back(b);
            t[b].push_back(a);
        }
        for (int i = 1; i <= n; i++)
        {
            cin >> weight[i];
        }
        dfs(1, 0);
        cout << maxlink << ' ' << tot << endl;
        return 0;
    }
  • 相关阅读:
    TWebBrowser 与 MSHTML(3): window 对象的属性、方法、事件纵览
    使 SaveDialog 对话框的文件名选择变灰 回复 "delphan" 的问题
    [最新通知]今日17:0019:00将不能访问博客园
    编辑器改进(三)
    博客园.Text技术支持移至PSP技术支持中心
    [公告]关于投稿到Dearbook的“读书笔记”专栏
    [致歉]博客园服务器停运时间超出计划时间
    [博客园公告]给发表评论增加了验证码功能
    CS Beta 1发布了
    [通知]11月6日(星期六)可能不能访问博客园
  • 原文地址:https://www.cnblogs.com/ssttkkl/p/7528792.html
Copyright © 2011-2022 走看看