IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> CF 1646D Weight the Tree 树形dp -> 正文阅读

[数据结构与算法]CF 1646D Weight the Tree 树形dp

题目链接

这道题拖了很长时间才去补,今天想起来做这道题

这道题的题意是可以组成合法的点互不相邻,我的思路没有错误,但是赛时没有写出代码,现在想想也觉得可惜,我要是多想到一个度的条件,赛时可能就会过了orz 。

首先前置芝士
没有上司的舞会
这道题和那个题几乎一模一样的代码,一样的推导过程,不过增加了限制,我赛时也是想出了雏形但是没有做出来。

然后分析推导过程

f ( u , 0 ) f ( u , 0 ) f(u,0) 表示当前点不选的子树(包含自己) , 可以选择的最多的点。
f ( u , 1 ) f (u , 1) f(u,1) 表示当前点选的子树(包含自己) , 可以选择的最多的点。

关系式子

f ( u , 1 ) f (u , 1) f(u,1) = 求和 f ( j , 0 ) f(j , 0) f(j,0)
f ( u , 0 ) f(u , 0) f(u,0) = 求和 m a x ( f ( j , 0 ) , f ( j , 1 ) ) max(f(j , 0) , f(j , 1)) max(f(j,0),f(j,1))

然后求和就是找度数之和最小的点,首先我们可以贪心不能组成的点为1,这样就可以贪心的让组成的点为它的度数啦 , 然后我们就可以开始愉快的敲代码 ac

代码如下

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std ;

const int N = 2e5 + 10 ;
const int M = 2 * N ;

int f[N][2] ;
int g[N][2] ;
int h[N] , e[M] , ne[M] , idx , d[N] ;
int ans[N] ;

void add(int a , int b)
{
	e[idx] = b , ne[idx] = h[a] , h[a] = idx ++ ;
	d[a] ++ ; 
}

void dfs(int u , int fa)
{
	f[u][1] = 1 ;
	g[u][1] = d[u] ;
	g[u][0] = 1 ;
	for(int i = h[u] ; ~i ; i = ne[i])
	{
		int j = e[i] ;
		if(j == fa) continue ;
		dfs(j , u) ;
		f[u][1] += f[j][0] ;
		g[u][1] += g[j][0] ;
		f[u][0] += max(f[j][0] , f[j][1]) ;
		if(f[j][0] > f[j][1])
			g[u][0] += g[j][0] ;
		else if(f[j][0] < f[j][1])
			g[u][0] += g[j][1] ;
		else 
			g[u][0] += min(g[j][0] , g[j][1]) ;
	}
}

void dfs(int u , int fa , int ty)
{
	if(!ty) ans[u] = 1 ;
	else ans[u] = d[u] ;
	for(int i = h[u] ; ~i ; i = ne[i])
	{
		int j = e[i] ;
		if(j == fa) continue ;
		if(ty)
			dfs(j , u , 0) ;
		else 
		{
			if(f[j][0] > f[j][1])
				dfs(j , u , 0) ;
			else if(f[j][0] < f[j][1])
				dfs(j , u , 1) ;
			else if(g[j][0] < g[j][1])
				dfs(j , u , 0) ;
			else 
				dfs(j , u , 1) ;
		}
	}
}
int main(void)
{
	memset(h , -1 , sizeof h) ;
	int n ;
	scanf("%d" , &n) ;
	for(int i = 1 ; i < n ; i ++)
	{
		int a , b ;
		scanf("%d%d" , &a , &b) ;
		add(a , b) , add(b , a) ;
	}
	if(n == 2)
	{
		puts("2 2") ;
		puts("1 1") ;
		return 0 ;
	}
	dfs(1 , 1) ;
	if(f[1][0] > f[1][1])
		dfs(1 , 1 , 0) , printf("%d %d\n" , f[1][0] , g[1][0]);
	else if(f[1][0] < f[1][1])
		dfs(1 , 1 , 1) , printf("%d %d\n" , f[1][1] , g[1][1]);
	else if(g[1][0] < g[1][1])
		dfs(1 , 1 , 0) , printf("%d %d\n" , f[1][0] , g[1][0]);
	else 
		dfs(1 , 1 , 1) , printf("%d %d\n" , f[1][1] , g[1][1]);
	for(int i = 1 ; i <= n ; i ++)
		printf("%d " , ans[i]) ;
}

在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:50:27  更:2022-03-15 22:55:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 17:08:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码