• [POI2008]STA-Station


    洛谷题目链接

    很明显而简单的树形$dp$:

    设以节点$v$为根时的深度和

    我们可以先处理出以$1$为根的深度和$f[1]$,那么我们怎么样才能不$dfs n$次来求出以其他点为根的深度和呢

    我们考虑现在节点为$u$,子节点为$v$,那么当$v$为根的时候,$f[v]=f[u]+n-2*siz[v]$($size[v]$为$v$子树大小),为什么呢,画张图,我们把$v$当做根,就是在把$u$当做根的基础上,$v$的子树深度都减少了$1$,总共减少了$siz[v]$,而其他节点的深度都$+1$,总共加了$n-siz[v]$

    代码:

    #include<iostream>
    #include<cstdio>
    #define N 1000007
    #define ll long long
    using namespace std;
    struct Edge
    {
    	int to,nxt;
    }edge[N<<1];
    int n,cnt;
    int head[N],siz[N],dep[N];
    ll f[N];
    void Add(int u,int v)
    {
    	edge[++cnt]=(Edge){v,head[u]};
    	head[u]=cnt;
    }
    void Dfs(int u,int fa)
    {
    	siz[u]=1;
    	dep[u]=dep[fa]+1;
    	f[1]+=dep[u];
    	for(int i=head[u];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==fa)
    			continue;
    		Dfs(v,u);
    		siz[u]+=siz[v];
    	}
    }
    void Dp(int u,int fa)
    {
    	for(int i=head[u];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==fa)
    			continue;
    		f[v]=f[u]+n-2*siz[v];
    		Dp(v,u);
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<n;++i)
    	{
    		int u,v;
    		scanf("%d%d",&u,&v);
    		Add(u,v);
    		Add(v,u);
    	}
    	Dfs(1,0);
    	Dp(1,0);
    	ll ans=0,maxn=0;
    	for(int i=1;i<=n;++i)
    		if(maxn<f[i])
    			ans=i,maxn=f[i];
    	printf("%lld",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    导弹拦截版
    [USACO1.5]数字三角形 Number Triangles
    FBI树
    修复公路
    台阶问题
    阶乘问题
    连续自然数和
    又是毕业季I
    生活大爆炸版石头剪刀布
    曹冲养猪
  • 原文地址:https://www.cnblogs.com/yexinqwq/p/10230152.html
Copyright © 2020-2023  润新知