首页 > 其他分享 >CLOI Round 2 D题题解

CLOI Round 2 D题题解

时间:2024-07-12 13:53:32浏览次数:21  
标签:int 题解 CLOI long Round dfs1 ans 节点 SIZE

一份简单的美术作业(Art)

题意:

给你一棵树,树上 \(n\) 个节点和 \(n-1\) 条边,每个点有一个权值,每两个黑点之间必须间隔至少一个白点,求黑点权值总和最大值,并且输出任意一种达成最大值的取点合法方案。

sol:

对于第一问,采用树形 dp。定义 \(f_{i,0/1}\) 为当前节点为 \(i\),当前点取或不取能其子树种达到的点权最大值,定义其子节点为 \(u\) 则有:

  • 当前节点不取,下面一个节点可以有取或不取两种选择,即 \(f_{i,0}=\sum\max\{f_{u,1},f_{u,0}\}\)。

  • 当前节点要取,下面一个节点不能取,即 \(f_{i,1}=w_i+\sum f_{u,0}\)。

最后答案就为 \(\max\{f_{root,0},f_{root,1}\}\)。

可以拿到 \(30\%\) 的分数。

第二问,可以在 dp 过程中加入一个 vector 数组 \(e\),对于每个子节点,如果取其结果最优,则在 \(e\) 中压入 \(1\),否则压入 \(0\)。

然后再进行一遍 dfs,如果这个节点在 \(e\) 中标号为 \(1\),说明这样决策最优,则它的子节点全部不能取,可以在递归的时候加入标记,如果标记为 \(0\) 则表示全部不取,把取到的数压入另一个 vector 数组 \(ans\) 中。

最后点的个数就是 ans.size(),方案就直接遍历 \(ans\) 数组输出。

复杂度 \(O(n\log n)\),\(\log\) 取在 vector 上。

最后,十年 OI 一场空,不开 long long 见祖宗。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define SIZE 100005

using namespace std;
int n, ver[2*SIZE], nxt[2*SIZE], head[SIZE], tot, cnt;
long long f[SIZE][2];
//f[i][0/1]表示当前处在第 i 个节点,当前节点染黑或不染黑,存储这个点的子树内染黑点权总和最大值 
long long w[2*SIZE];
vector<int> e[SIZE], ans;
void add(int x, int y){
	ver[++tot]=y, nxt[tot]=head[x], head[x]=tot;
}
void dfs(int x, int fa){
	f[x][1]=w[x];
	for (int i=head[x]; i; i=nxt[i]){
		int y=ver[i];
		if(y!=fa){
			dfs(y, x);
			f[x][1]+=f[y][0];
			f[x][0]+=max(f[y][1], f[y][0]);
			if(f[y][1]>f[y][0]) e[x].push_back(1);
			else e[x].push_back(0);
		}
	}
	return;
}
void dfs1(int x, int fa, bool flag){
	if(flag) ans.push_back(x);
	int cnt=0;
	for (int i=head[x]; i; i=nxt[i]){
		int y=ver[i];
		if(y!=fa){
			if(flag) dfs1(y, x, 0);
			else dfs1(y, x, e[x][cnt++]);
		}
	}
}
int main(){
	scanf("%d", &n);
	for (int i=1; i<=n; i++) scanf("%lld", &w[i]);
	for (int i=1; i<n; i++){
		int u, v;;
		scanf("%d%d", &u, &v);
		add(u, v);add(v, u);
	}
	dfs(1, 0);
	printf("%lld\n", max(f[1][1], f[1][0]));
	if(f[1][1]>f[1][0]) dfs1(1, 0, 1);
	else dfs1(1, 0, 0);
	printf("%lld ", ans.size());
	for (int i=0; i<ans.size(); i++) printf("%d ", ans[i]);
	
	return 0;
}

标签:int,题解,CLOI,long,Round,dfs1,ans,节点,SIZE
From: https://www.cnblogs.com/ylc666/p/18298225

相关文章

  • Codeforces Round 957 (Div. 3)
    E-Novice'sMistake题意为寻找n*a-b=("n"+"n"+...){a个n的字符串-b的长度}即为"2"⋅20−18="22222222222222222222"−18=22=2⋅20−18使用暴力枚举每个n相加的长度和又因为n<=100a<=100000所有答案t的值必定小于1e6所以对每个a进行枚举对于每个答案t进行判断是否成立其......
  • P1262 间谍网络 题解
    题目描述给你一个有向图,可以付出代价获取一些指定的点。在获取之后要求能以获取的点为出发点,将整个图都访问到,求最小的代价。思路既然需要令总的代价最少,那么如果通过买一个点就可以访问到的所有点,自然会比买两个点的方案更优。于是自然的就可以联想到可以将图划分成很多个强......
  • [ABC328D] Take ABC 题解
    题目翻译题目描述给你一个字符串\(S\)包含A、B和C三个不用的字符。只要字符串\(S\)中包含连续的ABC就将ABC删除掉再字符串\(S\)不能操作之后输出这个字符串限制\(S\)的长度小于\(2\times10^5\)思路1总结一下这道题目的操作,可以发现就是将字符串删除一......
  • [HNOI2005] 狡猾的商人's 题解
    题目描述给你一个\(n\)元一次方程,判断是否有解,方程给出的格式为\(a-b=c\)思路这道题看上去是一道题目看上去就是判断给出条件是否有矛盾,所以就自然而然的可以使用带权并查集但是因为我太懒了并且这道题目要求使用差分约束系统进行求解,于是就需要将题目转化一下因为差分约束......
  • Ubuntu系统下相关问题解决方案(亲测)
    系统:ubuntu20.04记录使用ubuntu系统过程中遇到的一些问题以及亲测有效的解决方案后续遇到其他问题,会将相关内容持续更新对应原文:Ubuntu系统下相关问题解决方案(亲测)-知乎(zhihu.com)目录一、速度问题1.1gitcloneGithub上的项目时速度慢1.2ubuntu下设置pip加速1.......
  • [CF1656G] Cycle Palindrome 的题解
    题目大意给定一个长度为\(n\)的数列\(a\),要求求出一个排列\(p\)满足\(a_{p_1},a_{p_2},\cdots,a_{p_n}\)是一个回文字符串而且把\(i\)向\(p_i\)连边得到的图中只有一个环。数据范围满足,\(1\le\sumn\le2\times10^5\)。思路先不考虑\(p\)是否构成满足要求的环......
  • [CF1646F] Playing Around the Table 的题解
    题目大意有\(n\)种牌,一种\(n\)张,一共\(n\)个玩家,一人\(n\)个。每个人一次将一张牌对给下家,求构造方案使可以在\(n\cdot(n-1)\)次操作之内使第\(i\)个人拥有\(n\)张\(i\)。数据范围满足,\(1\len\le100\)。思路因为直接构造出题目要求的情况会出现如果一个人提......
  • SMU Summer 2024 Contest Round 3
    1.To3原题链接:http://162.14.124.219/contest/1007/problem/I记录数组中除3余数的种类和个数,以及数组元素总和除3的余数,最后判断(考虑总余数为1,两个元素余数为2和总余数为2,两个元素余数为1的特殊情况)查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespa......
  • 2022 RoboCom CAIP(本科组)国赛个人题解
    RC-u1智能红绿灯为了最大化通行效率同时照顾老年人穿行马路,在某养老社区前,某科技公司设置了一个智能红绿灯。这个红绿灯是这样设计的:路的两旁设置了一个按钮,老年人希望通行马路时会按下按钮;在没有人按按钮的时候,红绿灯一直为绿灯;当红绿灯为绿灯时,有人按下按钮,第一次按下......
  • SMU Summer 2024 Contest Round 2
    1.MinimumWidth原题链接:http://162.14.124.219/contest/1006/problem/C二分一行最大容量,如果check小于等于总行数就扩大,反之则缩小查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intn,m;inta[1000000],b[1000000];boolcheck(intx){......