BZOJ1131&&洛谷 P3478 [POI2008]STA-Station

树形DP

思路

我们考虑暴力,从每个点 d f s dfs dfs,然后累加每个点的 d e p dep dep,然后取 m a x max max就好
如何优化
我们不难发现无论哪个点做根,对于他的一个子节点 v v v,若将 v v v转化为树的根,造成的影响是什么?发现对于v的子树,所有点的 d e p − 1 dep-1 dep1,对于 v v v子树外的点, d e p + 1 dep+1 dep+1,所以我们令 f [ r t ] f[rt] f[rt]表示 v v v的父节点做根时的 a n s ans ans,那么 f [ v ] = f [ r t ] − s i z [ v ] + n − s i z [ v ] = f [ r t ] + n − 2 ∗ s i z [ v ] f[v]=f[rt]-siz[v]+n-siz[v]=f[rt]+n-2*siz[v] f[v]=f[rt]siz[v]+nsiz[v]=f[rt]+n2siz[v],然后我们一开始把1当做根节点,dfs一遍,然后再向子树递推就好了

代码

//By AcerMo
#include
#include
#include
#include
#include
#define lli long long int
using namespace std;
const int M=2005000;
int n,m;
lli dep[M],siz[M],g[M],ans;
int to[M],nxt[M],head[M],cnt;
inline void read(int &x)
{
	x=0;char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	return ;
}
inline void add(int x,int y)
{ 
	to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;
	to[++cnt]=x;nxt[cnt]=head[y];head[y]=cnt;
	return ;
}
inline void dfs(int x,int f)
{
	dep[x]=dep[f]+1;
	siz[x]=1;g[1]+=dep[x];
	for (int i=head[x];i;i=nxt[i])
	if (f!=to[i]) 
	dfs(to[i],x),siz[x]+=siz[to[i]];
	return ;
}
inline void stat(int x,int f)
{
	if (g[x]>ans) ans=g[x],m=x;
	for (int i=head[x];i;i=nxt[i])
	if (to[i]!=f)
	{
		g[to[i]]=g[x]+n-2*1LL*siz[to[i]];
		stat(to[i],x);
	}
	return ;
}
signed main()
{
	read(n);int x,y;
	for (int i=1;i<n;i++)
	read(x),read(y),add(x,y);
	dep[0]=-1;dfs(1,0);stat(1,0);
	cout<<m; 
	return 0;
}

你可能感兴趣的:(动态规划)