NOIP 提高组2014 联合权值

本文讨论了如何优化解决树形结构中寻找所有距离为2的点对的点权乘积和最大乘积的问题。通过将树转化为有根树并记录节点信息,实现复杂度优化,避免了平方复杂度导致的超时问题。

        好久不发博客了,学弟挂了一组NOIP的题,第一次做这种赛制。。

        这个题是求一棵树上,所有距离为2的点对的点权的乘积的和,以及所有距离为2的点对的点权的乘积的最大值。开始用暴力写的,发现在一种特殊的情况下,所有点都和一个点相邻,复杂度就会达到平方,就会超时。

        经过优化后的做法是这样的。首先把树转为有根树,记录每个点的父亲,和所有孩子。一个点的任意两个孩子之间的距离一定是2,一个点与父亲的父亲距离一定是2。在求解一个点的2个孩子的权的乘积时,运用一点小技巧,就可以了。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <deque>

using namespace std;

const int mod = 10007;

vector<int> E[200010];

bool vis[200010];
int w[200010];
int fa[200010];
int lv[200010];
vector<int> sons[200010];	//存的是点所有孩子的权 
int MAX;
int cur;
long long tot;
int z;

void dfs(int u,int pre,int dep){
	int sz=E[u].size();
	lv[u]=dep;
	fa[u]=pre;
	for(int i=0;i<sz;i++){
		if(E[u][i]==pre)continue;
		sons[u].push_back(w[E[u][i]]);
		dfs(E[u][i],u,dep+1);
	}

}

int main(){
	MAX=tot=0;
	int n;
	cin>>n;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		
		E[u].push_back(v);
		E[v].push_back(u);
	}
	
	for(int i=1;i<=n;i++){
		scanf("%d",&w[i]);
	}
	
	dfs(1,0,0);
	
	for(int i=1;i<=n;i++){
		long long sum=0;
		//先全加起来,以降低复杂度 
		for(int j=0;j<sons[i].size();j++){
			sum+=sons[i][j];
		}
		for(int j=0;j<sons[i].size();j++){
			sum-=sons[i][j];
			tot+=sum* sons[i][j];
			
			tot%=mod;
			sum+=sons[i][j];
		}
		sort(sons[i].begin(),sons[i].end());
	
		if(sons[i].size()>1){
			MAX=max(MAX, sons[i][sons[i].size()-1] * sons[i][sons[i].size()-2] );
		}
	}
	
	for(int i=1;i<=n;i++){
		if(lv[i]>=2){
			int wx=w[i];
			int wy=w[fa[fa[i]]];
			int tmp=wx*wy;
			MAX=max(MAX,tmp);
			tot+=tmp;
			tot+=tmp;
			tot%=mod;
		}
	}
	
	cout<<MAX<<" "<<(tot)%mod<<endl;
	return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值