ABC223 G - Vertex Deletion(换根dp)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ABC223 G - Vertex Deletion(换根dp)相关的知识,希望对你有一定的参考价值。

Link

考虑定义 f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]表示子树 i i i内能匹配的最大数目(状态 0 / 1 0/1 0/1表示节点 i i i是否被使用)

f f f数组做一遍树形 d p dp dp就可以得到.然后考虑换根,也就是当除掉点 u u u后整棵树的最大匹配数目

想要得到除去 u u u后的最大匹配数分为两部分,一个是 u u u子树内,这部分显然就是

∑ ( u , v ) max ⁡ {   f [ v ] [ 0 ] , f [ v ] [ 1 ]   } \\sum\\limits_{(u,v)}\\max\\{\\ f[v][0],f[v][1]\\ \\} (u,v)max{ f[v][0],f[v][1] }

第二部分是以 u u u为根节点时往父亲节点延申的子树的最大匹配数记作 g [ u ] [ 0 / 1 ] g[u][0/1] g[u][0/1]

于是去掉节点 u u u的最大匹配数就是这两部分的和

考虑一个递推,也就是对于 u u u的儿子 v v v,能否处理出对应的 g [ v ] [ 0 ] , g [ v ] [ 1 ] g[v][0],g[v][1] g[v][0],g[v][1]

①.如果 v v v被使用,只能和 u u u匹配,此时的最大匹配数为

g [ u ] [ 0 ] + 1 + ∑ z ∈ s o n u & & z ! = v max ⁡ ( f [ z ] [ 0 ] , f [ z ] [ 1 ] ) g[u][0]+1+\\sum\\limits_{z\\in son_u\\&\\&z!=v}\\max(f[z][0],f[z][1]) g[u][0]+1+zsonu&&z!=vmax(f[z][0],f[z][1])

②.考虑如果 v v v不被使用,那么 u u u又分是否参与和儿子匹配两种情况

u u u不参与和儿子的匹配,显然最大匹配数为

max ⁡ ( g [ u ] [ 0 ] , g [ u ] [ 1 ] ) + ∑ z ∈ s o n u & & z ! = v max ⁡ ( f [ z ] [ 0 ] , f [ z ] [ 1 ] ) \\max(g[u][0],g[u][1])+\\sum\\limits_{z\\in son_u\\&\\&z!=v}\\max(f[z][0],f[z][1]) max(g[u][0],g[u][1])+zsonu&&z!=vmax(f[z][0],f[z][1])

u u u参与和儿子的匹配,设和儿子 k k k匹配,最大匹配数为

g [ u ] [ 0 ] + 1 + f [ k ] [ 0 ] + ∑ z ∈ s o n u & & z ! = k & & z ! = v max ⁡ {   f [ z ] [ 0 ] , f [ z ] [ 1 ]   } g[u][0]+1+f[k][0]+\\sum\\limits_{z\\in son_u\\&\\&z!=k\\&\\&z!=v}\\max\\{\\ f[z][0],f[z][1]\\ \\} g[u][0]+1+f[k][0]+zsonu&&z!=k&&z!=vmax{ f[z][0],f[z][1] }

看上去记录一个最大值为 m x 1 mx_1 mx1来对节点 v v v转移就行了,但是如果此时 k = v k=v k=v怎么办??

所以还需要记录以下次大值 m x 2 mx_2 mx2,当转移节点 v v v可以作为最大转移节点,就是用 m x 2 mx_2 mx2来转移

至此,已经完成了数组 g g g的递推,我们只需要知道 g g g数组的初值

也就是 g [ 1 ] [ 0 ] = 0 , g [ 1 ] [ 1 ] = − i n f g[1][0]=0,g[1][1]=-inf g[1][0]=0,g[1][1]=inf

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 3e5+10;
int n,mx,ans,f[maxn][2];
vector<int>vec[maxn];
void dfs1(int u,int fa = 0)
{
	bool flag = 1;
	for(auto v:vec[u] )
	{
		if( v==fa )	continue;
		dfs1( v,u ); flag = 0;
		f[u][0] += max( f[v][0],f[v][1] );
	}
	for(auto v:vec[u] )
	{
		if( v==fa )	continue;
		f[u][1] = max( f[u][1],f[u][0]-max( f[v][0],f[v][1] )+1+f[v][0] );
	}
	if( flag )	f[u][1] = -inf;//不可能 
}
void dfs2(int u,int fa = 0,int f0 = 0,int f1 = -inf )
{
	int now = 0;
	for(auto v:vec[u] )
	{
		if( v==fa )	continue;
		now += max( f[v][0],f[v][1] );
	}
	if( now+f0==mx )	ans++;
	int mx1 = 0, mx2 = 0;
	for(auto v:vec[u] )//节点u去匹配节点v时的最大和次大 
	{
		int nw = 0;
		if( v==fa )	continue;
		nw = now+f0-max( f[v][0],f[v][1] )+f[v][0]+1;
		if( nw>mx1 )	mx2 = mx1, mx1 = nw;
		else if( nw>mx2 )	mx2 = nw;
	}
	for(auto v:vec[u] )
	{
		if( v==fa )	continue;
		int nw = now+f0-max( f[v][0],f[v][1] )+f[v][0]+1;//当u,v匹配时
		int z = max( f[v][0],f[v][1] );
		int rx = now+f0+1-z;//(u,v)匹配起来 
		int ex = now+max(f0,f1)-z;//u不参与和儿子的匹配 
		if( nw==mx1 )	dfs2( v,u, max( ex,mx2-z ), rx );
		else	dfs2( v,u, max( ex,mx1-z ) ,rx ); 
	}
}
int main()
{
	cin >> n;
	for(int i=2;i<=n;i++)
	{
		int l,r; cin >> l >> r;
		vec[l].push_back( r ); vec[r].push_back( l );	
	}
	dfs1( 1 );
	mx = max( f[1][0],f[1][1] );
	dfs2( 1 );
	cout << ans;
}

以上是关于ABC223 G - Vertex Deletion(换根dp)的主要内容,如果未能解决你的问题,请参考以下文章

leetcode223

leetcode-223-矩形面积

R igraph:按条件标注顶点

223. Rectangle Area

leetcode 223 Rectangle Area

Leetcode 223 Rectangle Area