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

来源:互联网 发布:景观设计大数据 编辑:程序博客网 时间:2024/05/20 16:33

题目:

我是超链接

题意:

给一棵边带权的树,求哪些点在至少一条直径上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);}
原创粉丝点击