我是靠谱客的博主 欣慰御姐,最近开发中收集的这篇文章主要介绍2021 ICPC 南京 H-Crystalfly(树上DP)2021 ICPC 南京 H-Crystalfly(树上DP),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

2021 ICPC 南京 H-Crystalfly(树上DP)

Probelm Statement

你一开始处于 1 1 1号节点的树, 每个点 a i a_i ai个蝴蝶, 且如果 i t h i^{th} ith节点的父节点被扰动时, 这些蝴蝶会在 t i ( 1 ≤ t i ≤ 3 ) t_i(1leq t_ileq 3) ti(1ti3)时刻后消散. 求你可以抓到多少只蝴蝶.

Solution

当我们第一次到达节点 u u u的时候它的所有儿子都会被激活,对于 u u u的子节点 v v v, 我们只有两个决策, 要么到达子节点 v v v知乎继续向下, 那么 u u u的其他子节点上的蝴蝶都无法再次抓取. 或者我们进入某个子节点 v 1 ( t v 1 = 3 ) v_1(t_{v_1}=3) v1(tv1=3)后立刻返回节点 u u u挑另一个子节点 v 2 v_2 v2直接走下去, 然后除了 v 1 , v 2 v_1,v_2 v1,v2以外 u u u的其他子节点上的蝴蝶都会消失.

我们不妨设:

  • f i f_i fi: 我们取节点 i i i, 可以取 i i i子节点上的蝴蝶可以收获的最大蝴蝶数.
  • g i g_i gi: 我们不取节点 i i i上的蝴蝶, 可取 i i i子节点上的蝴蝶的最大蝴蝶数.
  • h i h_i hi: 我们节点 i i i上的蝴蝶, 但是不取 i i i子节点上的蝴蝶可以收获的最大蝴蝶数.

对于 h u h_u hu根据上述定义我们可以得到, h u = ∑ v ∈ son u g v + a u h_u=sumlimits_{vintext{son}u}g_v+a_u hu=vsonugv+au.

由于 f u f_u fu g u g_u gu的区别主要在于节点 u u u上的蝴蝶去不去得到, 我们有 f u = g u + a u f_u=g_u+a_u fu=gu+au.

接下来我们考虑计算 g u g_u gu根据上述两种两种决策:

请添加图片描述

Code

# define Fast_IO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
# include "unordered_map"
# include "algorithm"
# include "iostream"
# include "cstdlib"
# include "cstring"
# include "cstdio"
# include "vector"
# include "bitset"
# include "queue"
# include "cmath"
# include "map"
# include "set"
 
using namespace std;
 
const int maxm=1e5+10;
 
int Task,N;
long long A[maxm];
int T[maxm];
long long F[maxm],G[maxm],H[maxm];

vector<int> Edge[maxm];
 
void Dfs(int Now,int Father){
	long long Max1,Max2,Max; Max=Max1=Max2=0;
	long long Res=0;
	for(auto To:Edge[Now]){
		if(To==Father) continue;
		Dfs(To,Now);
	}H[Now]=A[Now];
	for(auto To:Edge[Now]){
		if(To==Father) continue;
		H[Now]+=G[To];
	}
	for(auto To:Edge[Now]){
		if(To==Father) continue;
		Res+=G[To];
		Max=max(A[To],Max);
	}G[Now]=Res+Max;
	Max1=Max2=0;
	for(auto To:Edge[Now]){
		if(To==Father || T[To]!=3) continue;
		if(A[To]>=Max1) Max2=Max1,Max1=A[To];
		else Max2=max(Max2,A[To]);
	}
	for(auto To:Edge[Now]){
		if(To==Father) continue;
		if(A[To]!=Max1 || T[To]!=3) G[Now]=max(G[Now],Res-G[To]+H[To]+Max1);
		else G[Now]=max(G[Now],Res-G[To]+H[To]+Max2);
	}
	F[Now]=G[Now]+A[Now];
	return;
}
 
inline void Solve(){
	static int i,U,V;
	scanf("%d",&N);
	for(i=1;i<=N;i++) Edge[i].clear(),F[i]=G[i]=false;
	for(i=1;i<=N;i++) scanf("%lld",&A[i]);
	for(i=1;i<=N;i++) scanf("%d",&T[i]);
	for(i=1;i< N;i++){
		scanf("%d%d",&U,&V);
		Edge[U].push_back(V);
		Edge[V].push_back(U);
	}Dfs(1,1);
	printf("%lldn",F[1]);
	return;
}
 
int main(){
	scanf("%d",&Task);
	while(Task--) Solve();
	return 0;
} 

Orz dls

算法来源: Namomo Camp Day1.

Link

Codeforces Gym: The 2021 ICPC Asia Nanjing Regional Contest(XXII Open Cup,Grand Prix of Nanjing).

Vjudge: Namomo Spring Camp 2022 Div1 Week1 A.

最后

以上就是欣慰御姐为你收集整理的2021 ICPC 南京 H-Crystalfly(树上DP)2021 ICPC 南京 H-Crystalfly(树上DP)的全部内容,希望文章能够帮你解决2021 ICPC 南京 H-Crystalfly(树上DP)2021 ICPC 南京 H-Crystalfly(树上DP)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部