CodeForces 【DP】1187E-Tree Painting

CodeForces 1187E Tree Painting

◇题目传送门◆

题目大意

给定一棵树,要求对 N N N个节点按如下方式涂色:

  • 第一次任选一个节点涂色,得分为 N N N
  • 此后任选一个与涂了色的节点连通的节点,将其涂色,得分为该节点所在的连通块中未涂色的节点个数。

确定一种涂色顺序使得得分最大化,输出这个最大值

分析

我们可以想到直接暴力枚举第一次涂的节点并贪心地涂下去,但这样做显然是超时的。

s i z [ u ] siz[u] siz[u]为以 u u u为根的子树中节点的个数。

我们考虑由 u u u转移到 v v v做根时,画一下图可发现,以 v v v为根的子树对答案的贡献减少了 s i z [ v ] siz[v] siz[v],以 u u u为根的子树对答案的贡献增加了 N − s i z [ v ] N-siz[v] Nsiz[v],所以我们只需DFS求出 s i z siz siz数组即可。

参考代码

#include<cstdio>
#include<algorithm>
using namespace std;
 
typedef long long ll;
const int Maxn=2e5;
 
int N;
vector<int> G[Maxn+5];
void addedge(int u,int v) {
	G[u].push_back(v);
	G[v].push_back(u);
}
 
ll f[Maxn+5];
int siz[Maxn+5];
void DFS1(int u,int fa) {
	siz[u]=1;
	for(int i=0;i<G[u].size();i++) {
		int v=G[u][i];
		if(v==fa)continue;
		DFS1(v,u);
		siz[u]+=siz[v];
		f[u]+=f[v];
	}
	f[u]+=siz[u];
}
ll ans;
void DFS2(int u,int fa,ll val) {
	ans=max(ans,val);
	for(int i=0;i<G[u].size();i++) {
		int v=G[u][i];
		if(v==fa)continue;
		DFS2(v,u,val+(N-siz[v])-siz[v]);
	}
}
 
int main() {
	#ifdef LOACL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	scanf("%d",&N);
	for(int i=1;i<N;i++) {
		int u,v;
		scanf("%d %d",&u,&v);
		addedge(u,v);
	}
	DFS1(1,-1);
	DFS2(1,-1,f[1]);
	printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值