[vijos1476]旅游规划(csapc)(树形dp)

树形DP求直径节点
本文介绍了一种使用动态规划解决树形结构中求直径问题的方法,并提供了完整的C++实现代码。通过两次DFS遍历,分别计算每个节点的最长路径和次长路径,最终找出处于树直径上的所有节点。

题目:

我是超链接

题意:

给一棵边带权的树,求哪些点在至少一条直径上n<=200000

题解:

这里用dp比较方便,f[i]最长g[i]次长
这次从上到下,先算父亲再算孩子,h[i]表示i向除子树外最远距离

代码:

#include <cstdio>  
#include <iostream>  
#define N 200005 
using namespace std;  
int tot,nxt[N*2],point[N],v[N*2],ans[N],f[N],g[N],n,i,maxx,anss,h[N];  
void addline(int x,int y)  
{  
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; 
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}  
void treedp(int x,int fa)  
{  
    for (int i=point[x];i;i=nxt[i])  
      if (v[i]!=fa)  
      {  
        treedp(v[i],x);  
        if (f[v[i]]+1>f[x])  
        {  
            g[x]=f[x];  
            f[x]=f[v[i]]+1;  
        }  
        else g[x]=max(g[x],f[v[i]]+1);  
      }  
    maxx=max(maxx,f[x]+g[x]);  
}  
void dfs(int x,int fa)
{
    int cnt=0;
    for (int i=point[x];i;i=nxt[i])
      if (v[i]!=fa) if (f[x]==f[v[i]]+1) cnt++;
    for (int i=point[x];i;i=nxt[i])
      if (v[i]!=fa)     
      {
        if (f[x]!=f[v[i]]+1 || (f[x]==f[v[i]]+1 && cnt>1)) h[v[i]]=max(h[x],f[x])+1;
        else h[v[i]]=max(h[x],g[x])+1;
        dfs(v[i],x);
      }
}
int main()  
{  
    scanf("%d",&n);  
    for (i=1;i<n;i++)  
    {  
        int a,b;  
        scanf("%d%d",&a,&b);a++;b++;  
        addline(a,b);   
    }  
    treedp(1,0);  
    dfs(1,0);
    for (i=1;i<=n;i++) 
      if (f[i]+max(g[i],h[i])==maxx)  ans[++anss]=i;
    for (i=1;i<=anss;i++) printf("%d\n",ans[i]-1);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值