首页 > 其他 > 详细

Luogu P1351 联合权值

时间:2019-10-08 15:37:50      阅读:84      评论:0      收藏:0      [点我收藏+]

gate

第一反应是树形dp,讨论兄弟和爷爷两种情况。想了想觉得不够优雅就去看了题解…

优雅的做法是枚举中间点!

设当前点为x,x所连的点为(a,b,c,...)

对于求最大值,只要每次记录x连接的最大的两个点,并检查更新答案即可。

因为求有序点对,所以(a,b)(b,a)都会被算一次。

那么x的最终贡献即为$2ab+2ac+2bc+...$

它等价于$(a+b+c+...)^2 - (a^2+b^2+c^2...)$

注意:取模的时候因为有减法,必须保证答案为正数。

代码如下

技术分享图片
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;

const int maxn = 4e5+10;
const int mod = 10007;
int n,x,y,m1,m2,s1,s2;
int w[maxn],head[maxn],to[maxn],nxt[maxn];
int M,ans,cnt;

void add(int x,int y) {
    to[++cnt] = y;
    nxt[cnt] = head[x];
    head[x] = cnt;
}

int main() {
    scanf("%d",&n);
    for(int i = 1; i <= n-1; i++) {
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    for(int i = 1; i <= n; i++)
        scanf("%d",&w[i]);
    for(int k = 1; k <= n; k++) {
        m1 = m2 = s1 = s2 = 0;
        for(int i = head[k]; i; i = nxt[i]) {
            int v = to[i];
            if(w[v] > m1) {
                m2 = m1;
                m1 = w[v];
            } else if(w[v] > m2) m2 = w[v];
            s1 = (s1 + w[v]) %mod;
            s2 = (s2 + w[v]*w[v]) %mod;
        }
        M = max(M,m1*m2);
        ans = (ans + (s1*s1%mod) %mod - s2 + mod)%mod;
    }
    printf("%d %d",M,ans);
    return 0;
}
View Code

 

Luogu P1351 联合权值

原文:https://www.cnblogs.com/mogeko/p/11635526.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!