题解 NOIP2014 提高组-联合权值

题解 NOIP2014 提高组-联合权值

基本思路:以每个点为中转点,则与之相邻的点组成的点对都可产生联合权值,并且全覆盖。

主要总结一下两种求权值和的思路:

思路1(容斥):记与 \(u\) 相邻的点的集合为 \(A\),则点 \(u\) 产生的贡献为

\[ans_u=(\sum_{v \in A}w_i)^2-\sum_{v \in A}w_v \times w_v \]

对于每个中转点 \(u\) ,枚举 \(v\) 的同时直接求这两个式子,循环外结算。

void dfs(int u,int f){
	ll tot=0,cz=0,cmax=-1,dmax=-1;
	for(auto v:g[u]){
		tot+=w[v];
		cz=(cz+w[v]*w[v]%mod)%mod;
		if(w[v]>cmax) dmax=cmax,cmax=w[v];
		else if(w[v]>dmax) dmax=w[v];
		if(v!=f) dfs(v,u);
	}
	ans=(ans+tot*tot%mod-cz)%mod;
	mx=max(dmax*cmax,mx);
}

思路2(在线统计答案):在枚举到 \(v_i\) 时,考虑先让它和 \(v_{1 \sim i-1}\) 组合,最后输出时将答案乘2即可。

void dfs(int u,int f){
	ll tot=0,cmax=-1,dmax=-1;
	for(auto v:g[u]){
		ans=(ans+tot*w[v])%mod;
		tot+=w[v];
		if(w[v]>cmax) dmax=cmax,cmax=w[v];
		else if(w[v]>dmax) dmax=w[v];
		if(v!=f) dfs(v,u);
	} 
    mx=max(dmax*cmax,mx);
}
  • 重点记录一下思路2,没有尝试过这种思路。
posted @ 2024-01-27 09:48  superl61  阅读(15)  评论(0编辑  收藏  举报