HDU - 6409

题目链接:HDU - 6409


假设一次都不能选一对兄弟。

那么我们肯定是贪心,对每个节点选最大的权值的儿子,现在可以选一对兄弟,那么我们选一个最优的次大值加上即可。

最小值同理。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f3f3f3f3f;
int n,a[N],mx1[N],mx2[N],mi1[N],mi2[N],res1,res2,mmx,mmi;
vector<int> g[N];
void dfs(int x){
	for(int to:g[x]){
		dfs(to);
		if(a[to]>mx1[x])	mx2[x]=mx1[x],mx1[x]=a[to];
		else if(a[to]>mx2[x]) mx2[x]=a[to];
		if(a[to]<mi1[x])	mi2[x]=mi1[x],mi1[x]=a[to];
		else if(a[to]<mi2[x]) mi2[x]=a[to];
	}
	if(mx1[x]>0)	res1+=mx1[x];
	if(mi1[x]<0)	res2+=mi1[x];
	mmx=max(mmx,mx2[x]),mmi=min(mmi,mi2[x]);
}
inline void solve(){
	cin>>n; mmx=-inf,mmi=inf; res1=res2=0;
	for(int i=1;i<=n;i++)	g[i].clear(),mx1[i]=mx2[i]=-inf,mi1[i]=mi2[i]=inf;
	for(int i=2,x;i<=n;i++)	scanf("%lld",&x),g[x].push_back(i);
	for(int i=1;i<=n;i++)	scanf("%lld",&a[i]);
	if(a[1]>0)	res1=a[1];
	if(a[1]<0)	res2=a[1];
	dfs(1);
	printf("%lld %lld\n",res1+max(0LL,mmx),res2+min(0LL,mmi));
}
signed main(){
	int T; cin>>T; while(T--) solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107623965
hdu