首页 > 其他分享 >换根DP学习笔记

换根DP学习笔记

时间:2024-03-25 13:58:50浏览次数:25  
标签:dfs rep LL 笔记 DP 换根 dp define

啊啊啊啊啊啊啊啊啊啊啊啊画图累死我了

额,这不菜根快乐DP()吗

换根DP,即换根树形DP

平常树形DP指定一个根,但万一邪恶出题人让你求多个点为根的情况呢?

你们可能会想:多跑几遍不就好了!

不可以的,直接TLE。

这有个树,B是A之后的树根(拎上去):

B成为树根后:

画风突然转变

但是!其实有些没变!

只需要处理一点点就好啦~

直接开题来学:https://www.luogu.com.cn/problem/CF1324F

Let me give you an example:(我英语不好别笑我)

(图中的数左边是白个数,右边是黑)

我就不算结果了哈我很懒

以A为根时,A的两个子树的结果到了现在都可以用!(造福...祖先?)

B左子树也可以用!

把A的原来的最左子树(不太严谨意思到了就行)删掉(跟B是一样的)

再处理A和B

就这样,超级简单!

代码:

#include<stdio.h>
#include<bits/stdc++.h>
#define N 1000010
#define MOD 998244353
#define esp 1e-8
#define INF 999999999999999999
#define LL long long
#define rep(i,a,b,g) for(LL i=a;i<=b;i+=g)
#define rem(i,a,b,g) for(LL i=a;i>=b;i-=g)
#define repn(i,a,b,g) for(LL i=a;i<b;i+=g)
#define remn(i,a,b,g) for(LL i=a;i>b;i-=g)
#define pll pair<LL,LL>
#define mkp(x,y) make_pair(x,y)
#define i128 __int128
#define lowbit(x) ((x)&(-(x)))
#define lc (u<<1)
#define rc (u<<1|1)
using namespace std;
void read(i128 &x)
{
	i128 f=1;
	x=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
void write(i128 x)
{
	if(x>=10)write(x/10);
	putchar(x%10+'0');
}
LL n;
LL a[200010],dp[200010],sum[200010];
vector<LL>g[200010];
void dfs(LL v,LL p)
{
	dp[v]=a[v];
	for(auto u:g[v])
	{
		if(u==p)continue;
		dfs(u,v);
		dp[v]+=max(0LL,dp[u]);
	}
}
void sfd(LL v,LL p)
{
	sum[v]=dp[v];
	for(auto u:g[v])
	{
		if(u==p)continue;
		dp[v]-=max(0LL,dp[u]);
		dp[u]+=max(0LL,dp[v]);
		sfd(u,v);
		dp[u]-=max(0LL,dp[v]);
		dp[v]+=max(0LL,dp[u]);
	}
}
int main()
{
	cin>>n;
	rep(i,1,n,1)
	{
		cin>>a[i];
		if(!a[i])a[i]=-1;
	}
	rep(i,1,n-1,1)
	{
		LL u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0);
	sfd(1,0);
	rep(i,1,n,1)cout<<sum[i]<<' ';
	return 0;
}

https://www.luogu.com.cn/problem/CF1187E

这题还挺简单的

因为,拿脑子想想可以发现,确定第一个点后,后面选点的顺序就不影响权值了

为啥?读者自证不难

那就变成了第一个选哪个最好

直接就 换根DP(唉,不是两个字),启动!

用 \(g_x\) 表示先选x能得到的权值

咋转移?

拿眼睛看可以得出:

\[g_y=n+\left ( n-size_y \right ) +\sum_{i\in son_x|i\neq y}^{} f_i+\sum_{i\in son_y}^{} f_i \]

中间过程不写了

最终可以推出

\[g_y=g_x+n-2\times size_y \]

哦对了,\(f_x\) 表示 \(x\) 的子树对它的贡献

代码:

#include<bits/stdc++.h>
#define N 200010
#define LL long long
#define rep(i,a,b,g) for(LL i=a;i<=b;i+=g)
using namespace std;
LL n,s[N],f[N],g[N],mc,u,v;
vector<LL>e[N];
void dfs(LL u,LL fa)
{
	s[u]=1;
	for(LL i=0;i<e[u].size();i++)
	{
		LL v=e[u][i];
		if(v==fa)continue;
		dfs(v,u);
		s[u]+=s[v];
		f[u]+=f[v];
	}
	f[u]+=s[u];
}
void sfd(LL u,LL fa)
{
	if(u!=1)
	{
		g[u]=g[fa]+n-s[u]*2;
		mc=max(mc,g[u]);
	}
	for(LL i=0;i<e[u].size();i++)
	{
		LL v=e[u][i];
		if(v==fa)continue;
		sfd(v,u);
	}
}
int main()
{
	cin>>n;
	rep(i,1,n-1,1)
	{
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(1,0);
	mc=g[1]=f[1];
	sfd(1,0);
	cout<<mc<<endl;
	return 0;
}

https://www.luogu.com.cn/problem/P3478

更简单了

思路不写了,转移自己推去(手酸)

代码:

#include<bits/stdc++.h>
#define N 1000010
#define LL long long
#define rep(i,a,b,g) for(int i=a;i<=b;i+=g)
using namespace std;
struct ed
{
	LL u,v,ne;
}e[2*N];
LL d[N];
LL o,h[4*N],s[N],n,dw[N],up[N],f[N],u,v;
void add(LL u,LL v)
{
	e[++o]=(ed){u,v,h[u]};
	h[u]=o;
}
void dfs(LL u,LL fa)
{
	s[u]=1;
	for(LL i=h[u];i;i=e[i].ne)
	{
		LL v=e[i].v;
		if(v==fa)continue;
		f[v]=u;
		d[v]=d[u]+1;
		dfs(v,u);
		s[u]+=s[v];
		dw[u]+=dw[v]+s[v];
	}
}
void sfd(LL u)
{
	if(u!=1)
	{
		up[u]=up[f[u]]+dw[f[u]]-dw[u]-2*s[u]+n;
	}
	for(LL i=h[u];i;i=e[i].ne)
	{
		LL v=e[i].v;
		if(v==f[u])continue;
		sfd(v);
	}
}
int main()
{
	cin>>n;
	rep(i,1,n-1,1)
	{
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	dfs(1,0);
	sfd(1);
	LL mc=0,t;
	rep(i,1,n,1)
	{
		if(up[i]+dw[i]>mc)mc=up[i]+dw[i],t=i;
	}
	cout<<t<<endl;
	return 0;
}

然后树上依赖背包要多练。

标签:dfs,rep,LL,笔记,DP,换根,dp,define
From: https://www.cnblogs.com/cppom/p/-/gengengengen

相关文章

  • 高斯消元学习笔记
    注:此篇一直在讲高斯-约旦消元法。https://oi-wiki.org/math/numerical/gauss/相信大家都读过上面那个wiki。大家其实都看得挺懵的对吧。今天我就来教一下大家高斯消元。技术指导:milk,周百万,TB\(\LaTeX\)指导:不是你觉得这文章\(\LaTeX\)很好吗?所以没有指导。首先小学知识......
  • 容斥原理学习笔记
    一个很重要的东西首先为了方便我们规定\[0^0=1\]也就是说\[0^n=\left[n=0\right]\]你们可能会说:“啊火神这个\([]\)是啥啊?”\[[P]称为Iverson括号,P是一个命题,若P为真则[P]=1,否则[P]=0。\]OIer话:类似bool。这个规定超级有用,有用在哪你们待会就知道了。朴素集合论“......
  • 多媒体笔记
    人类感知信息的途径:视觉占65%,听觉占20%,嗅觉、味觉、触觉占15%信息量。 3D视频比2D视频多了深度一维。 视频图像压缩的基本依据:1)空间冗余;2)频率冗余;3)视觉冗余;4)熵冗余;5)时间冗余。 视频图像压缩的基本方法:1)帧内预测编码;2)变换编码;3)量化编码;4)熵编码;5)帧间预测编码。 ......
  • 矩阵乘法学习笔记
    还是那句话,作者\(\LaTeX\)超级差。定义首先矩阵定义扔出来:域\(K\)上的一个\(n×m\)的矩阵可以看作一个\(n×m\)的数表。记为:\[A_{n×m}=\begin{bmatrix}A_{1,1}&\cdots&A_{1,m}\\\vdots&\ddots&\vdots\\A_{n,1}&\cdots&A_{n,m}\end{bmatrix}\]矩阵加法soeasy.......
  • 莫队学习笔记
    模板。然后我不会做。然后我去看题解,看莫队学习笔记,看不懂。然后我摆烂了。然后去玩按住shift让光标左右动的无聊游戏。我最开始选中了标红点的部分。多选中了左边的一个点,少选中了右边的一个点。然后我会莫队了?......
  • 吴恩达机器学习笔记第六章逻辑回归分析以及代码实现
    第六章对线性代数和导数的要求比之前几章是要高一些的,对于对应的数学知识点我会在下方顺便仔细地指出来并在能力范围内给予一定的推导,尽量保证各位能明白不用再查来查去的,不用重蹈我的覆辙......
  • 吴恩达机器学习实践笔记,第四章的多元梯度下降的实现
    https://blog.csdn.net/out_look520/article/details/107695529这个链接里面有需要的数据集,有需要的兄弟姐妹们自己解决哟,我下面的数据就是从那个博主那里拿的今天实践了一下多元梯度下降哈,其实道理和原来二元的一样,也是采用下面这个式子只是θ的数量多了一些而已,废话不多......
  • yolov9学习笔记
    一、准备工作1、github下载yolov9代码WongKinYiu/yolov9:Implementationofpaper-YOLOv9:LearningWhatYouWanttoLearnUsingProgrammableGradientInformation(github.com)2、下载anaconda国内镜像下载:Indexof/anaconda/archive/|清华大学开源软件镜像站......
  • 百度【灵境矩阵】智能体开发初学笔记
    AIAgent(人工智能代理)是一种能够感知环境、进行决策和执行动作的智能实体。AIAgent可以称为“智能体”,也可以理解为“智能业务助理”,指在大模型技术驱动下,让人们以自然语言为交互方式高自动化地执行和处理专业或繁复的工作任务,从而极大程度释放人员精力。灵境矩阵是百度推出的......
  • 二级建造师2024年学习笔记
    导读:2024年新增8节:侵权责任制度:概念、构成要件、特殊侵权税收制度:增值税、环境保护税行政法律制度:行政许可、强制、处罚刑事法律制度:犯罪、犯罪的构成、特殊罪名、减刑假释建筑市场主体:自然人、法人、其它经济组织营商环境:中小企业支付保护、民营经济公平营商环境要求非......