zoukankan      html  css  js  c++  java
  • P1351 联合权值 题解

    CSDN同步

    原题链接

    简要题意:

    给定一棵树,每两个距离为 (2) 的点 (u,v) 会产生 (w_u imes w_v) 的“联合权值”。求 “联合权值” 的和,以及所有联合权值中的最大值。

    其实这题作为 ( ext{NOIP 2014tg Day1T2}),并不难。

    首先考虑:距离为 (2) 的点只有两种情况:

    1. 爷爷和孙子的关系。

    2. 弟弟和哥哥的关系。

    具体到树上就是,(u=fa_{fa_v}),或者 (fa_u = fa_v),都会产生 (w_u imes w_v) 的贡献。

    对于求最大值,我们可以遍历每个节点 (i),统计 (i) 的爷爷和自己的贡献,以及所以 (fa_u = fa_v = i) 的最大值,取出 (i) 儿子中的最大值和次大值即可。

    对于求和,我们发现,如果 (u) 的第 (v) 个儿子为 (sub_{u,v}),且共 (k) 个儿子,则贡献为:

    [sum_{i=1}^k sum_{j=i+1}^k w_{sub_{u,i}} imes w_{sub_{u,j}} ]

    [=frac{ sum_{i=1}^k sum_{j=1}^k w_{sub_{u,i}} imes w_{sub_{u,j}} - sum_{i=1}^k w_{sub_{u,i}} imes w_{sub_{u,i}} }{2} ]

    (两两的乘积,先总的重复计算,减去自己乘自己的,交换 (div 2)

    [= frac{ igg ( sum_{i=1}^k w_{sub_{u,i}} igg )^2 -sum_{i=1}^k ( w_{sub_{u,i}} )^2}{2} ]

    太精妙了!!!

    所以统计 平方和和的平方 即可。平方和和和的平方

    时间复杂度:(O(n)).

    实际得分:(100pts).

    细节:总和要取模,最大值不用。

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const ll MOD=1e4+7;
    const int N=2e5+1;
    
    inline int read(){char ch=getchar();int f=1; while(!isdigit(ch)) {if(ch=='-') f=-f; ch=getchar();}
    	   int x=0;while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}
    
    ll n,w[N];
    vector<int> G[N];
    vector<int> son[N];
    ll ans1,ans2;
    
    inline void dfs(ll dep,ll fa,ll gr) {
    //正在处理 dep,父亲节点为 fa,祖父(爷爷) 节点为 gr
    	ll zd=0,cd=0,sum1=0,sum2=0;
    	for(ll i=0;i<G[dep].size();i++) {
    		ll v=G[dep][i];
    		if(v!=fa) {
    			sum1=(sum1+w[v])%MOD;
    			sum2=(sum2+w[v]*w[v]%MOD)%MOD; //两边一起统计
    			if(w[v]>zd) cd=zd,zd=w[v];
    			else if(w[v]>cd) cd=w[v]; //最大值,次大值
    			dfs(v,dep,fa); //往下搜索
    		}
    	} sum1=(sum1*sum1)%MOD; //和的平方
    	ans1=max(ans1,max(cd*zd,w[dep]*w[gr])); //统计最大值
    	ans2=(ans2+(sum1+MOD-sum2)%MOD+w[dep]*w[gr]*2%MOD)%MOD; //统计和
    }
    
    int main(){
    	n=read();
    	for(ll i=1;i<n;i++) {
    		ll u=read(),v=read();
    		G[u].push_back(v);
    		G[v].push_back(u);
    	} for(ll i=1;i<=n;i++) w[i]=read();
    	dfs(1,0,0);
    	printf("%lld %lld
    ",ans1,ans2);
    	return 0;
    }
    
    
  • 相关阅读:
    LeetCode 3Sum Closest
    LeetCode Jump Game
    LeetCode Convert Sorted List to Binary Search Tree
    LeetCode Search for a Range
    LeetCode ZigZag Conversion
    sql server中主键列的插入问题
    php 联系电话验证(手机和固话)
    Update与Mysql、Sqlsever中的随机数
    Yii在nginx下多目录rewrite
    php后台判断ajax请求
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12642140.html
Copyright © 2011-2022 走看看