首页 > 其他分享 >arc179d 题解

arc179d 题解

时间:2024-06-06 12:34:01浏览次数:9  
标签:min 传送门 题解 arc179d dep int dp

arc179d

思路

设计树形 dp。\(dp_{u,0}\) 表示进子树 \(u\) 并不再出去的代价。\(dp_{u,1}\) 表示进子树 \(u\) 并返回,且传送门在 \(fa\)、不在子树内使用传送门的代价。\(dp_{u,2}\) 表示进入子树 \(u\) 并返回,且可以在子树内使用传送门。

发现 \(dp_{u,1}\) 一定是遍历子树最后到子树中最深的点通过传送门返回,一定是 \(2\times siz_u+\max (dep_i-dep_u)\)。\(dp_{u,0}\) 和 \(dp_{u,2}\) 的唯一区别在于 \(dp_{u,0}\) 最后进入的一个子树不用返回。

\[dp_{u,2}=\sum \max(dp_{v,1}+1,dp_{v,2}+2),dp_{u,0}=dp_{u,2}+\min (dp_{v,0}+1-\min(dp_{v,1}+1,dp_{v,2}+2)) \]

然后换根 dp。考虑 \(\max (dep_i-dep_u)\) 和 \(\min (dp_{v,0}+1-\min(dp_{v,1}+1,dp_{v,2}+2))\) 的转移,需要记录最大值和次大值。

code

int n,ans=inf;
int head[maxn],tot;
struct nd{
	int nxt,to;
}e[maxn<<1];
void add(int u,int v){e[++tot]={head[u],v};head[u]=tot;}
int dp[maxn][3],siz[maxn];
pii dep[maxn],mn[maxn];
void dfs(int u,int fa){
	siz[u]=1;mn[u].fi=mn[u].se=0,dep[u].fi=dep[u].se=0;
	if(u!=1&&!e[head[u]].nxt){dp[u][0]=dp[u][1]=dp[u][2]=0;return ;}
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		dfs(v,u);siz[u]+=siz[v];
		if(dep[u].fi<dep[v].fi+1)dep[u].se=dep[u].fi,dep[u].fi=dep[v].fi+1;
		else if(dep[u].se<dep[v].fi+1)dep[u].se=dep[v].fi+1;
		int val=dp[v][0]+1-min(dp[v][1]+1,dp[v][2]+2);
		if(val<mn[u].fi)mn[u].se=mn[u].fi,mn[u].fi=val;
		else if(val<mn[u].se)mn[u].se=val;
		dp[u][0]+=min(dp[v][1]+1,dp[v][2]+2);
		dp[u][2]+=min(dp[v][1]+1,dp[v][2]+2);
	}
	dp[u][0]+=mn[u].fi;dp[u][1]=(siz[u]-1)*2-dep[u].fi;
	// cout<<u<<" "<<dp[u][0]<<" "<<dp[u][1]<<" "<<dp[u][2]<<"\n";
}
void dfs1(int u,int fa){
	ans=min(ans,dp[u][0]);
	// cout<<u<<" "<<dp[u][0]<<" "<<dp[u][1]<<" "<<dp[u][2]<<"\n";
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		int u0=dp[u][0],u1=dp[u][1],u2=dp[u][2];pii du=dep[u],mnu=mn[u];
		siz[u]-=siz[v],siz[v]+=siz[u];
		if(dep[u].fi==dep[v].fi+1)dep[u].fi=dep[u].se;
		int val=dp[v][0]+1-min(dp[v][1]+1,dp[v][2]+2);
		if(mn[u].fi==val)mn[u].fi=mn[u].se;
		dp[u][1]=(siz[u]-1)*2-dep[u].fi;
		dp[u][2]-=min(dp[v][1]+1,dp[v][2]+2);
		dp[u][0]=dp[u][2]+mn[u].fi;
		
		if(dep[v].fi<dep[u].fi+1)dep[v].se=dep[v].fi,dep[v].fi=dep[u].fi+1;
		else if(dep[v].se<dep[u].fi+1)dep[v].se=dep[u].fi+1;
		val=dp[u][0]+1-min(dp[u][1]+1,dp[u][2]+2);
		if(val<mn[v].fi)mn[v].se=mn[v].fi,mn[v].fi=val;
		else if(val<mn[v].se)mn[v].se=val;
		dp[v][0]+=min(dp[u][1]+1,dp[u][2]+2);
		dp[v][2]+=min(dp[u][1]+1,dp[u][2]+2);
		dp[v][0]=dp[v][2]+mn[v].fi;dp[v][1]=(siz[v]-1)*2-dep[v].fi;
		
		dfs1(v,u);
		dp[u][0]=u0,dp[u][1]=u1,dp[u][2]=u2;dep[u]=du,mn[u]=mnu;
		siz[v]-=siz[u],siz[u]+=siz[v];
	}
}
void work(){
	n=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	dfs(1,0);
	dfs1(1,0);
	printf("%lld\n",ans);
}

标签:min,传送门,题解,arc179d,dep,int,dp
From: https://www.cnblogs.com/yhddd/p/18234905

相关文章

  • abc355f 题解
    abc355f直接贺lct维护mst的代码。思路观察到\(w_i\le10\),考虑分开建\(10\)个图表示边权小于等于\(i\)的边组成的图。连并查集,记录当前图连了\(siz_i\)条边。可以发现第\(i-1\)个图是第\(i\)个图的子图。所以差分\(siz_i-siz_{i-1}\)可以得到原图的最小生成......
  • CF1575E 题解
    CF1575E思路点分治,记录当前子树到分治中心的权值和和换车次数。将新子树的答案合并时分类讨论分治中心到子树祖先\(u\tov\)的颜色。树状数组维护前缀和。复杂度\(O(n\log^2n)\)。codeintn,k,a[maxn],ans;inthead[maxn],tot;structnd{ intnxt,to,fl;}e[maxn<<1];......
  • abc355e 题解
    abc355e思路WC2024T3中知道一个技巧:如果知道区间\([l,r]\)的和就连边\(l\tor+1\),那么想推出\([L,R]\)的区间和就要求\(L\)和\(R+1\)联通。按题意把符合要求的边连上,设边权为\(1\)跑bfs,求出\(L\)到\(R+1\)的最短路并记录路径上的点,就可以得到要询问的区间。......
  • CF1007B 题解
    CF1007B思路显然题目要求计数\(u\midA,v\midB,w\midC\)。\(O(n\sqrtn)\)预处理出每个数的所有因数,记为集合\(p_i\)。容斥,记集合\(a,b,c,ab,ac,bc,all\)为\(p_A,p_B,p_C,p_A\capp_B,p_A\capp_A,p_B\capp_C,p_A\capp_B\capp_C\)。可以用bitset维护交集。首先加......
  • 【面试宝藏】MySQL 面试题解析
    MySQL面试题解析1.数据库三大范式是什么?第一范式(1NF):确保每列的原子性,即每列不能再分。第二范式(2NF):在满足1NF的基础上,每个非主属性完全依赖于主键,即消除部分依赖。第三范式(3NF):在满足2NF的基础上,任何非主属性不依赖于其他非主属性,即消除传递依赖。2.MySQL有关权限......
  • 【面试宝藏】Redis 常见面试题解析其二
    Redis高级面试题解析20.说说Redis哈希槽的机制?Redis集群采用哈希槽(HashSlot)机制来分布和管理数据。整个哈希空间被划分为16384个槽,每个键通过CRC16校验后取模映射到一个哈希槽。每个节点负责一部分哈希槽,从而实现数据分片和负载均衡。21.Redis集群的主从复制......
  • P4785 [BalticOI 2016 Day2] 交换 题解
    看到\(i\)和\(\lfloor\frac{i}{2}\rfloor\),考虑一颗二叉树。题目的操作相当于按顺序交换当前节点和左右儿子的权值。假设当前考虑的节点为\(id\),左儿子为\(ls\),右儿子为\(rs\),当前这些点的值分别为\(A,B,C\)。因为\(id\)的位置最靠前,最终又要字典序最小,所以要尽可能......
  • 题解:SP1442 CHAIN - Strange Food Chain
    双倍经验:P2024[NOI2001]食物链思路:一眼鉴定为并查集。观察题目发现有三种状态,考虑使用种类并查集(又称扩展域并查集)。既然有三种状态那么种类并查集自然也要开三倍。CODE:#include<bits/stdc++.h>usingnamespacestd;intfa[150010];intGet_Find(intx){//寻找父节点......
  • P1654 OSU! 题解
    P1654OSU!题解题目链接好题!但不得不说早期洛谷的题解质量是真的差,感觉没有一篇题解是讲的特别清楚的,我看了好久才搞懂。下面是我认为的一种更规范的解题过程。首先,我们设随机变量\(X_i\)表示从\(i\)向左的极长1串的长度,并且对于任意的\(i\),我们要想办法求出\(E(X_i......
  • (第26天)【leetcode题解】226、翻转二叉树 589、N叉树的前序遍历 590、N叉树的后序遍
    目录226、翻转二叉树题目描述思路代码589、N叉树的前序遍历题目描述思路代码590、N叉树的后序遍历题目描述思路代码思考总结226、翻转二叉树题目描述给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。示例:输入:root=[4,2,7,1,3,6,9]输出:[4,7,2,9,......