首页 > 其他分享 >【LuoGu】1351 联合权值

【LuoGu】1351 联合权值

时间:2023-09-02 21:22:50浏览次数:73  
标签:std 结点 int LuoGu 1351 联合 权值 sum

[NOIP2014 提高组] 联合权值

题目描述

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

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

输入格式

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

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

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

20 74

提示

本例输入的图如上所示,距离为 \(2\) 的有序点对有\((1,3)\) 、\((2,4)\) 、\((3,1)\) 、$(3,5) \(、\)(4,2)$ 、$(5,3) $。

其联合权值分别为 \(2,15,2,20,15,20\)。其中最大的是 \(20\),总和为 \(74\)。

【数据说明】

  • 对于 \(30\%\) 的数据,\(1 < n \leq 100\);
  • 对于 \(60\%\) 的数据,\(1 < n \leq 2000\);
  • 对于 \(100\%\) 的数据,\(1 < n \leq 2\times 10^5\),\(0 < W_i \leq 10000\)。

保证一定存在可产生联合权值的有序点对。

解决方案

注意到题目所给图为一棵树(\(n\)个点,\(n-1\)条边),因此图中一定无环。
因此对于距离为\(2\)的点就只有两种情况:
1、祖父-孙子结点
2、兄弟结点
注意到上述两种情况都存在一个中间结点,假定为\(u\)。1,2两种情况都可以归到\(u\)的邻接结点。
因此,我们可以枚举所有的点\(u\),然后遍历所有与\(u\)相邻的结点来得到我们想要的答案。
现在来看如何求解题目所需要的答案:
最大联合权值
对于一个中间结点\(u\),它的所有邻接结点能够产生的最大联合权值等于邻接结点中最大权值点乘以次大权值点。因此只需要在遍历过程中维护两个变量\(maxw1, maxw2\)来记录最大权值与次大权值即可。
联合权值和
假设\(u\)有\(n\)个邻接点\(x_1, x_2, ..., x_n\)。联合权值之和\(sumw\)等于\(2\sum_{i=1}^n\sum_{j=1}^nx_ix_j\)。直接计算的话时间复杂度会到平方级别,会\(TLE\)。因此需要另寻他法(数学)
假设\(n=2\),我们可以发现:\((x_1 + x_2)^2=x_1^2+x_2^2+2x_1x_2\)。其中后面的\(2x_1x_2\)就是我们要求的。
推广到任意正整数\(n > 2\),有\((\sum_{i=1}^nx_i)^2=\sum_{i=1}^nx_i^2+2\sum_{i=1}^n\sum_{j=1}^n x_ix_j\).
因此对于一个中间结点产生的联合权值和等于\((\sum_{i=1}^nx_i)^2-\sum_{i=1}^nx_i^2\)。只需要在遍历过程中已经遍历过的结点的权值和即可。

#include<bits/stdc++.h>

const int N = 200010, MOD = 10007;

int n;
std::vector<std::vector<int>> g(N);
int w[N];
int answ, maxw;

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	std::cin >> n;
	for(int i = 0; i < n - 1; i ++ ){
		int u, v;
		std::cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}

	for(int i = 1; i <= n; i ++ ){
		std::cin >> w[i];
	}

	for(int i = 1; i <= n; i ++ ){
		int sumsq = 0, sqsum = 0;
		int maxw1 = 0, maxw2 = 0;
		for(auto v:g[i]){
			if(w[v] > maxw1){
				maxw2 = maxw1;
				maxw1 = w[v];
			}
			else if(w[v] > maxw2){
				maxw2 = w[v];
			}
			sumsq = (sumsq + w[v]) % MOD;
			sqsum = (sqsum + w[v] * w[v]) % MOD;
		}
		sumsq = sumsq * sumsq % MOD;
		answ = (answ + sumsq - sqsum + MOD) % MOD;
		maxw = std::max(maxw, maxw2 * maxw1);
	}

	std::cout << maxw << " " << answ;
	return 0;
}

标签:std,结点,int,LuoGu,1351,联合,权值,sum
From: https://www.cnblogs.com/yjx-7355608/p/17674209.html

相关文章

  • 【题解】Luogu[P7706] 「Wdsr-2.7」文文的摄影布置
    Link一道很有意思的线段树题。第一步分析,我们要求最大的\(a_i+a_k-\min{(b_j)}\),事实上我们可以直接省去这个\(\min\)因为要最大化这个东西,选出来的\(b_j\)必然是最小的,所以原题转化为给定\(l,r\)求\(\max{(a_i-b_j+a_k)}\)其中\(i<j<k\)。第二步分析,我们发现这是一......
  • 【题解】Luogu-P2482 SDOI2010 猪国杀
    写了\(358\)行,\(11.94\mathrm{KB}\),有这么几个地方写挂了:反猪决斗一定选主猪。游戏结束判定是主猪死亡或全部反猪死亡。决斗可能被反杀,之后不能再出牌。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,m;charCh[3];queue<char>Deck;in......
  • 线段树+动态开点权值线段树+主席树学习笔记
    线段树一般用于维护符合结合律的信息。可以用于求区间最大值区间和区间最小值最大子段和甚至于最大负数最小正数之类的信息。事实上线段树只有你想不到,很少有做不到的,算是相当常用的数据结构。下面将结合个人理解和具体题目来讲一讲线段树。[https://www.luogu.com.cn/proble......
  • LuoguP7637 [BalticOI 2006 Day 1] BITWISE EXPRESSIONS
    题目大意给定\(N\)对数据,每对数据包含两个整数\(A_i\)和\(B_i\),表示这一对数据的\(v_i\)的范围:\(A_i\leqv_i\leqB_i\)。又将这\(N\)对数据分为\(P\)组,其中\(K_i\)表示第\(i\)组数据中有多少对数据。我们设第\(i\)组数据中将所有数按位与的结果为\(X_i\),求......
  • [刷题笔记] Luogu P2285 [HNOI2004] 打鼹鼠
    ProblemAnalysis我们初始可以任意决定机器人的位置,状态很多,暴力显然会寄掉。不妨先贪心的思考一下。我们肯定希望机器人初始在最先出现鼹鼠的洞,因为出现在没有鼹鼠的洞是无效的。题目保证输入数据是严格按照出现时间递增顺序给出。定义\(f_i\)表示前\(i\)只鼹鼠最多能打到......
  • [刷题笔记] Luogu P4933 大师
    ProblemDescription给定一个长度为\(n\)的数组\(h\),你可以从中选取若干数字,使得你选择的数组组成一个等差数列。特别地,单一的数字和只有两个数字也算作等差数列。求你可选择的方案数。答案对\(998244353\)取模。Analysis考虑\(f_{i,j}\)表示前\(i\)个数,公差为\(j\)......
  • [刷题笔记] Luogu P1064 [NOIP2006 提高组] 金明的预算方案
    ProblemAnalysis我们发现如果忽略主从关系,那这道题就是一个裸的01背包问题。主从关系处理也非常简单,借鉴P2014选课的经验,转换成树上背包问题。同理,本题是一个森林,若将0号节点参与建树的话就可以把森林转换成树,处理方便。具体地,设\(f_{i,j}\)表示以\(i\)为父节点,剩......
  • [刷题笔记] Luogu P2679 [NOIP2015 提高组] 子串
    ProblemDescription我们可以换个思路。从字符串\(A\)中拿出\(k\)个字串使其变成\(B\)。求有几种不同的方案?Analysis我们发现\(A\)中的一个字符取或者不取影响后面的决策,这并不代表它一定有后效性,我们可以记录这一层状态。和最长公共子序列同理,定义\(f_{i,j,k,l}(\fo......
  • [刷题笔记] [【LGR-155-Div.3】T4] Luogu P9572 「NnOI R2-T4」Colorful Days♪
    ProblemDescription有两个数组\(A,B\),我们可以将\(A\)数组无限次重复拼接。求最少需要多少次拼接使得拼接后的\(A,B\)的最长公共子序列最大。Analysis我们要学会从题目中找到一些信息,比如说本题的数据范围:对于\(100\%\)的数据,保证\(1\leqn,m,S_i,T_i\le10^6\),\(......
  • Luogu P1119 灾后重建
    在洛谷中查看解法1(我想的解法,不完全正确):很常见的套路:将询问按时间排序。时间复杂度:\(O(\;q\,(n\,logn+m)\;)\),即\(10^9\),开\(O2\)才能过。非常麻烦有没有,但我对拍的时候发现了一组数据很奇怪,待会给你们看看,我看看能不能hack#include<bits/stdc++.h>usingnamespacestd......