2020CCPC秦皇岛 k题 Kingdom’s Power(树上DP O(n) 复杂度)

本文介绍了两种O(N)复杂度的算法解法,用于解决特定类型的问题。第一种解法利用动态规划思想,通过递归计算每个节点的最优解,以达到全局最优。第二种解法则重新设计了动态规划的状态定义,使得状态转移更加直观易懂。

发现网上都是o(nlogn)的写法,没有o(n)的,所以这里贴一下代码,简单讲解一下(感觉好像很难讲明白,我实在是太菜了QAQ)

做法1:刚看题时的思路,不是很好理解,建议看做法2

显然如果派出一支军队访问子树,并回到子树根节点,那消耗的时间就是边长的2倍。首先,显然军队从根出发,经过一些路径后停留在叶子节点明显最优。考虑多引一支军队到达叶子节点,则该军队会先走过一段被其他军队走过的路径,会额外消耗一些时间。到达子树根节点后,子树根节点到某个叶子节点这段只用走一次,可以节省这段路径长度的时间。

dp[x]表示只考虑x节点所在的子树以及x指向父亲的那条边,至少多派一支军队走到x所在子树的叶子节点(且已经有其他军队进过x子树的父亲节点,且之前没有任何一个军队会走到x子树的叶子节点),最少会多消耗多少时间(负数表示能节省时间)。

转移的时候,如果有子树额外引一支军队能节省时间(即dp值小于0),那显然引一个军队走到该子树会使答案更优,如果没有任何一支军队dp值小于0,则选额外消耗时间最少的那一颗子树多派一支军队

#include<bits/stdc++.h>
 
using namespace std;
 
int dp[1001000];
int n;
vector<int>edg[1001000];
int Ti = 0;
void dfs(int now, int d) {
	if(edg[now].size() == 0) {
		dp[now] =  (d-1) - 1;
		return;
	}
	
	int sum = 0;
	int num = 0;
	int minn = 10000000;
	for (int i = 0; i < edg[now].size(); i++) {
		int nex =  edg[now][i];
		dfs(nex, d+1);
		if (dp[nex] <= 0) {
			num++;
			sum+=dp[nex];
		}
		minn = min(minn, dp[nex]);
	}
	if (num
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值