首页 > 其他分享 >【BZOJ4987】Tree(树形dp)

【BZOJ4987】Tree(树形dp)

时间:2022-10-28 20:02:52浏览次数:58  
标签:min int 路径 Tree BZOJ4987 cdots dp size

题意:给你一棵 \(n\) 个节点的树找出 \(k\) 个不同的点 \(a_1,a_2,\cdots,a_k\),
使得 \(\sum\limits_{i=1}^{k-1} dis(a_i,a_{i+1})\) 最小。

首先有个容易想到的性质:这 \(k\) 个点一定是相邻的,那么选 \(k\) 个点可以看成选 \(k-1\) 条相连的边。

但关键是我们不是要算一个环的长度,而是一条路径的长度,也就是说不用算从终点再走回到起点的距离,事情就变得麻烦起来。

用树形 dp 求解:设 \(dp(i,j,0/1/2)\) 表示在 \(i\) 子树中,选出 \(j\) 条边的方案数。

其中第 \(3\) 维是 \(0\) 表示这条路径的两个端点都在根节点 \(i\) 上;第 \(3\) 维是 \(1\) 表示这条路径的两个端点一个在根节点 \(i\) 上,另一个在 \(i\) 的子树内;第 \(3\) 维是 \(2\) 表示这条路径的两个端点都在 \(i\) 的子树内,但是这条路径经过 \(i\)。

那么答案就是 \(\min\limits_{i=1}^n dp(i,k-1,0/1)\)。

然后转移也比较明显,主要是这个时间复杂度的证明。

证法一:

设对于某一个点 \(u\),以 \(u\) 为根的子树大小为 \(s\),\(u\) 的儿子的子树大小分别为 \(s_1,s_2,\cdots,s_m\)。

那么在 \(u\) 节点的时间是:

\[\begin{aligned} &s_1+s_1*s_2+(s_1+s_2)s_3+(s_1+s_2+s_3)s_4+\cdots+\left(\sum_{i=1}^{m-1}s_i\right)s_m\\ \approx&s_1*s_2+(s_1+s_2)s_3+(s_1+s_2+s_3)s_4+\cdots+\left(\sum_{i=1}^{m-1}s_i\right)s_m\\ <&2\left(s_1*s_2+(s_1+s_2)s_3+(s_1+s_2+s_3)s_4+\cdots+\left(\sum_{i=1}^{m-1}s_i\right)s_m\right)\\ =&s_1(s_2+s_3+\cdots+s_m)+s_2(s_1+s_3+s_4+\cdots+s_m)+s_3(s_1+s_2+s_4+\cdots+s_m)\\ =&s_1(s-s_1-1)+s_2(s-s_2-1)+s_3(s-s_3-1)+\cdots+s_m(s-s_m-1)\\ =&s(s_1+\cdots+s_m)-(s_1^2+s_2^2+\cdots-s_m^2)-(s_1+s_2+\cdots+s_m) <&s(s_1+\cdots+s_m)-(s_1^2+s_2^2+\cdots-s_m^2)\\ =&s(s-1)-(s_1^2+s_2^2+\cdots-s_m^2)\\ <&s^2-s_1^2-s_2^2-\cdots-s_m^2 \end{aligned}\]

然后每两层相消,最后总时间复杂度就是根所代表的子树的大小的平方,即 \(O(n^2)\)。

证法二:

dp 的实质可以看做枚举树中的点对 \((u,v)\),然后当且仅当存在某一个 \(root\),使得 \(u\) 和 \(v\) 分别在 \(root\) 的两个儿子的子树中。显然,对于每一个点对 \((u,v)\),有且仅有一个 \(root=\operatorname{lca}(u,v)\)。所以总时间复杂度是 \(O(n^2)\)。

代码如下:

#include<bits/stdc++.h>

#define N 3010
#define ll long long
#define INF 0x7fffffff

using namespace std;

int n,k,size[N];
int cnt,head[N],nxt[N<<1],to[N<<1];
ll w[N<<1],dp[N][N][3];
//dp[0]:根进根出
//dp[1]:根进子树内出
//dp[2]:子树内进子树内出(经过根) 

void adde(int u,int v,ll wi)
{
	to[++cnt]=v;
	w[cnt]=wi;
	nxt[cnt]=head[u];
	head[u]=cnt;
}

void dfs(int u,int fa)
{
	size[u]=1;
	dp[u][0][0]=dp[u][0][1]=0;
	for(int i=head[u];i;i=nxt[i])
	{
		int v=to[i];
		if(v==fa) continue;
		dfs(v,u);
		for(int j=size[u]-1;j>=0;j--)
		{
			for(int k=size[v]-1;k>=0;k--)
			{
				dp[u][j+k+1][0]=min(dp[u][j+k+1][0],dp[u][j][0]+dp[v][k][0]+w[i]*2);
				dp[u][j+k+1][1]=min(dp[u][j+k+1][1],min(dp[u][j][0]+dp[v][k][1]+w[i],dp[u][j][1]+dp[v][k][0]+w[i]*2));
				dp[u][j+k+1][2]=min(dp[u][j+k+1][2],min(dp[u][j][0]+dp[v][k][2]+w[i]*2,min(dp[u][j][1]+dp[v][k][1]+w[i],dp[u][j][2]+dp[v][k][0]+w[i]*2)));
			}
		}
		size[u]+=size[v];
	}
}

int main()
{
	memset(dp,127,sizeof(dp));
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++)
	{
		int u,v;ll w;
		scanf("%d%d%lld",&u,&v,&w);
		adde(u,v,w),adde(v,u,w);
	}
	dfs(1,0);
	ll ans=INF;
	for(int i=1;i<=n;i++)
		ans=min(ans,min(dp[i][k-1][1],dp[i][k-1][2]));
	printf("%lld\n",ans);
	return 0;
}

标签:min,int,路径,Tree,BZOJ4987,cdots,dp,size
From: https://www.cnblogs.com/ez-lcw/p/16837307.html

相关文章

  • TreeMap
    (1)TreeMap跟TreeSet底层原理一样,都是红黑树结构的。(2)由键决定特性:不重复、无索引、可排序。(3)可排序:对键进行排序。(4)注意:默认按照键的从小到大进行排序,也可以自己规定键的......
  • 【BZOJ2212】【POI2011】【XSY2014】Tree Rotation(线段树合并)
    输入格式真的毒瘤权值线段树合并。我们先对每一个叶子建一棵权值线段树,并把它自己的权值插入到里面。我们不妨设原树中当前节点为\(u\),爸爸\(fa\),左儿子\(lc\),右儿子......
  • 【BJWC2018】上学路线(dp,Lucas,crt)
    考虑dp。我们先把\((n,m)\)也当做障碍点,然后把所有的障碍点按\(x\)坐标为第一关键字,\(y\)坐标为第二关键字排序。然后设\(f_i\)表示到达第\(i\)个障碍点的合法......
  • 【ARC074E】RGB Sequence(神奇的dp)
    注意到颜色的种类数只有\(3\)种,\(n\leq100\)也很小。然后就有了一种神奇的dp状态:考虑从前往后填方块,设\(dp(i,j,k)\)表示离当前位置最近的颜色位置在\(i\),离当......
  • 【ARC068F】Solitaire(dp,计数,思维)
    首先发现那个双端队列一定长这样:也就是说,这个队列中的数先单调递减,然后再单调递增,最小值为\(1\)。现在考虑从双端队列中取数,那么当我们取到\(1\)这个数时,我们会在原......
  • 【AGC023F】01 on Tree(树上一类全序问题)
    显然如果没有树的限制,我们优先选\(0\),然后选\(1\)。如果有了树的限制,我们考虑下面这么一种贪心方法:假设当前能够选的点的集合为\(S\)(初始时\(S\)只包含根),然后选出\(......
  • 【AGC013D】Piling Up(神奇的dp)
    考场上用了一种奇怪的做法,不知道为什么就对了,考完后仔细想才想明白。很巧妙的一种dp方式。首先发现每次操作是拿一个球、放两个球、再拿一个球,总球数不变,所以有\(\tex......
  • 【AGC005D】_K Perm Counting(容斥,二分图,计数dp)
    首先正面做不太好做,考虑容斥。设\(f(m)\)表示排列中至少有\(m\)处\(|P_i-i|=k\)的方案数。那么答案就是\(\sum\limits_{i=0}^n(-1)^if(i)\)。原题可以看成一个二......
  • 【AGC003F】Fraction of Fractal(dp,矩阵快速幂)
    先说一下下文会用到的定义或称呼的意思:称单位分形为题目给出的\(1\)级分形。称一种分形左右联通,则说明将两个这种分形左右放在一起时,至少有一个连通块是跨越这两个......
  • 【51Nod1386】双马尾机器人(分块+dp)
    对于这种找互质的数的集合的题,一般是讨论每个数的质因子会不会有重复。听说这种互质的题把质因子分为小于\(\sqrt{n}\)和大于\(\sqrt{n}\)是经典套路?因为当\(n\)很......