更好的阅读体验

Portal

Portal1: Luogu

Portal2: LibreOJ

Description

无向连通图\(\mathrm G\)有\(n\)个点,\(n - 1\)条边。点从\(1\)到\(n\)依次编号,编号为\(i\)的点的权值为\(W_i\) ,每条边的长度均为\(1\)。图上两点\((u, v)\)的距离定义为\(u\)点到\(v\)点的最短距离。对于图\(\mathrm G\)上的点对\((u, v)\),若它们的距离为\(2\),则它们之间会产生\(W_u \times W_v\)的联合权值。

请问图\(\mathrm G\)上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?

Input

第一行包含\(1\)个整数\(n\)。

接下来\(n - 1\)行,每行包含2个用空格隔开的正整数\(u, v\),表示编号为\(u\)和编号为\(v\)的点之间有边相连。

最后\(1\)行,包含\(n\)个正整数,每两个正整数之间用一个空格隔开,其中第\(i\)个整数表示图\(\mathrm G\)上编号为i的点的权值为\(W_i\)。

Output

输出共\(1\)行,包含\(2\)个整数,之间用一个空格隔开,依次为图\(\mathrm G\)上联合权值的最大值和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对\(10007\)取余。

Sample Input

5
1 2
2 3
3 4
4 5
1 5 2 3 10

Sample Output

20 74

Solution

我们先看一下题目:无向连通图\(\mathrm G\)有\(n\)个点,\(n - 1\)条边。

不难发现题目给出的是一颗树。

我们看一个例子:

这个图的联合权值和为\(W_2 \times W_3 + W_4 \times W_5 + W_4 \times W_6 + W_5 \times W_6 + W_7 \times W_8\)。

不难发现,我们求的是对于每一棵子树的非根节点的所有子结点两两相乘的权值和。但是我们对每一棵子树都遍历一遍显然要超时。我们可以找到如下性质:

\((a + b) ^ 2 = a ^ 2 + b ^ 2 + 2ab​ \\\ (a + b + c) ^ 2 = a ^ 2 + b ^ 2 + c ^ 2 + 2ab+ 2ac + 2bc \\\ (a + b + c + d) = a ^ 2 + b ^ 2 + c ^ 2 + d ^ 2 + 2ab+ 2ac + 2ad + 2bc + 2bd + 2cd \\\ \cdots \cdots\)

我们要求的就是平方项后面的一半。就是 \(\texttt{和的平方} - \texttt{平方的和}\) 。

统计最大值是只需要找出最大的两项,然后相乘就可以了。

这样就这道题就解决了。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath> using namespace std; typedef long long LL;
const int INF = 0x3f3f3f3f, MAXN = 400005, MAXM = 200005, mod = 10007;
struct EDGE {
int to, nxt;
} edge[MAXN];
int n, u, v, cnt, w[MAXM], head[MAXN];
inline void addedge(int u, int v) {
edge[++cnt].to = v; edge[cnt].nxt = head[u]; head[u] = cnt;
}
int main() {
scanf("%d", &n);
memset(head, -1, sizeof(head));
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);//加边
}
for (int i = 1; i <= n; i++)
scanf("%d", &w[i]);
LL Max = -INF, ans = 0;
for (int i = 1; i <= n; i++) {
LL Max1 = -INF, Max2 = -INF, tot1 = 0, tot2 = 0;//Max1表示最大的权值,Max2表示第二大的权值,tot1表示和的平方,tot2表示平方的和
for (int j = head[i]; ~j; j = edge[j].nxt) {//遍历每一个点
if (w[edge[j].to] > Max1) {
Max2 = Max1;
Max1 = w[edge[j].to];
} else
if (w[edge[j].to] > Max2 && w[edge[j].to] <= Max1) Max2 = w[edge[j].to];//找两个最大的
tot1 += w[edge[j].to]; tot2 = (tot2 + w[edge[j].to] * w[edge[j].to]) % mod;//累计当前点的权值
}
tot1 = (tot1 % mod * tot1 % mod) % mod;//和的平方
ans = (ans + tot1 - tot2 + mod) % mod;//累加答案
Max = max(Max, Max1 * Max2);//找最大权值
}
printf("%lld %lld\n", Max, ans);
return 0;
}

Attachment

测试数据下载:https://www.lanzous.com/i5q1vdg

『题解』洛谷P1351 联合权值的更多相关文章

  1. 洛谷 P1351 联合权值 题解

    P1351 联合权值 题目描述 无向连通图 \(G\) 有 \(n\) 个点,\(n-1\) 条边.点从 \(1\) 到 \(n\) 依次编号,编号为 \(i\) 的点的权值为 \(W_i\)​,每条 ...

  2. [NOIP2014] 提高组 洛谷P1351 联合权值

    题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...

  3. 洛谷 P1351 联合权值

    题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...

  4. 洛谷——P1351 联合权值

    https://www.luogu.org/problem/show?pid=1351 题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i , ...

  5. 洛谷P1351 联合权值(树形dp)

    题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...

  6. 洛谷 P1351 联合权值 —— 树形DP

    题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...

  7. 洛谷P1351 联合权值

    \(\Large\textbf{Description:}\) \(\large一棵树,父子之间距离为1,求距离为2的两点点权之积的最大值与和.\) \(\Large\textbf{Solution: ...

  8. 『题解』洛谷P1063 能量项链

    原文地址 Problem Portal Portal1:Luogu Portal2:LibreOJ Portal3:Vijos Description 在\(Mars\)星球上,每个\(Mars\)人 ...

  9. 『题解』洛谷P1993 小K的农场

    更好的阅读体验 Portal Portal1: Luogu Description 小\(K\)在\(\mathrm MC\)里面建立很多很多的农场,总共\(n\)个,以至于他自己都忘记了每个农场中种 ...

随机推荐

  1. spring5 源码深度解析----- 事务增强器(100%理解事务)

    上一篇文章我们讲解了事务的Advisor是如何注册进Spring容器的,也讲解了Spring是如何将有配置事务的类配置上事务的,实际上也就是用了AOP那一套,也讲解了Advisor,pointcut验 ...

  2. B-线性代数-矩阵转置

    [TOC] 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:https://www.cnblogs.com/nickchen121/ ...

  3. C++学习笔记-预备知识

    1.1 C++简介 C++融合3种不同的编程方式:C语言代表的过程性语言.C++在C语言基础上添加的类代表的面向对象语言.C++模板支持的广泛编程. 1.2 C++简史 1.2.1 C语言 Ritch ...

  4. css3——box-sizing属性

    很多朋友们可能会疑惑,不知道box-sizing属性是有什么作用,自己也很少会用到,但是想必不少人在做网页布局的时候经常遇到一个问题就是我明明设置了父元素设置了假如是宽高500px,5个子元素左浮动设 ...

  5. Redis Sentinel(哨兵核心机制) 初步深入

    ##### 1.Redis 的 Sentinel 系统用于管理多个 Redis 服务 该系统执行以下三个任务:  1.监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务 ...

  6. 从零学习基于Python的RobotFramework自动化

    从零学习基于Python的RobotFramework自动化 一.        Python基础 1)      版本差异 版本 编码 语法 其他 2.X ASCII try: raise Type ...

  7. unittest中diascover批量执行用例

    # case_dir='./'#当前脚本的路径 # discover=unittest.defaultTestLoader.discover(case_dir,pattern='unittest_fr ...

  8. php代码Xdebug调试使用笔记

    0x01 Xdebug简介 Xdebug是一个开放源代码的PHP程序调试器 运行流程: 0x02  Xdebug配置 日志 xdebug.trace_output_dir: 日志追踪输出目录 xdeb ...

  9. java学习1-初始java程序

    # 第一个简单示例 public class Hello { public static void main(String[] args) { System.out.println("Hel ...

  10. postman使用实例

    以下以一个登录接口为例,介绍一下postman是如何发请求的. 先执行Pre-request Scripts(预处理) - body - tests(进行断言) postman中变量的引用: {{}}