树的直径

树的直径

1.树形DP求树的直径

void dp(int x)
{
   v[x]=1;
   for(int i=head[x];~i;i=edge[i].next){
       Edge e=edge[i];
       if(v[e.to]) continue;
       dp(e.to);
       ans=max(ans,d[x]+d[e.to]+e.w);
       d[x]=max(d[x],d[e.to]+e.w);
  }
}

2.两次BFS求树的直径(非负边权)

# include <bits/stdc++.h>
using namespace std;

const int MAXN=1e5+100;
const int INF=1e9;
struct Edge{
   int next,to,w;
}edge[MAXN<<1];
int tot=2;
int head[MAXN];
void add(int u,int v,int w)
{
   edge[tot].w=w;
   edge[tot].to=v;
   edge[tot].next=head[u];
   head[u]=tot++;
}

int ans=-INF,id;
int v[MAXN],f[MAXN];
void dfs(int b,int dis)
{
   v[b]=1;
   int flag=0;
   for(int i=head[b];~i;i=edge[i].next){
       Edge e=edge[i];
       if(v[e.to]) continue;
       flag=1;
       f[e.to]=i;
       dis+=e.w;
       dfs(e.to,dis);
       dis-=e.w;
  }
   v[b]=0;
   if(flag==0){
       if(dis>ans) ans=dis,id=b;
       return ;
  }
}
int main()
{
   int cntt=0;
   memset(head,-1,sizeof(head));
   int n,k; scanf("%d%d",&n,&k);
   cntt=2*(n-1);
   for(int i=1;i<n;i++){
       int a,b; scanf("%d%d",&a,&b);
       add(a,b,1);
       add(b,a,1);
  }
   dfs(1,0);
   memset(v,0,sizeof(v));
   ans=-INF; f[id]=0;
   dfs(id,0);
   cntt-=ans-1;

   printf("%d\n",cntt);
   return 0;
}

两个方法都用的一个例题

# include <bits/stdc++.h>
using namespace std;

const int MAXN=1e5+100;
const int INF=1e9;
struct Edge{
   int next,to,w;
}edge[MAXN<<1];
int tot=2;
int head[MAXN];
void add(int u,int v,int w)
{
   edge[tot].w=w;
   edge[tot].to=v;
   edge[tot].next=head[u];
   head[u]=tot++;
}

int ans=-INF,id;
int v[MAXN],f[MAXN];
void dfs(int b,int dis)
{
   v[b]=1;
   int flag=0;
   for(int i=head[b];~i;i=edge[i].next){
       Edge e=edge[i];
       if(v[e.to]) continue;
       flag=1;
       f[e.to]=i;
       dis+=e.w;
       dfs(e.to,dis);
       dis-=e.w;
  }
   v[b]=0;
   if(flag==0){
       if(dis>ans) ans=dis,id=b;
       return ;
  }
}
int d[MAXN];
void dp(int x)
{
   v[x]=1;
   for(int i=head[x];~i;i=edge[i].next){
       Edge e=edge[i];
       if(v[e.to]) continue;
       dp(e.to);
       ans=max(ans,d[x]+d[e.to]+e.w);
       d[x]=max(d[x],d[e.to]+e.w);
  }
}
int main()
{
   int cntt=0;
   memset(head,-1,sizeof(head));
   int n,k; scanf("%d%d",&n,&k);
   cntt=2*(n-1);
   for(int i=1;i<n;i++){
       int a,b; scanf("%d%d",&a,&b);
       add(a,b,1);
       add(b,a,1);
  }
   dfs(1,0);
   memset(v,0,sizeof(v));
   ans=-INF; f[id]=0;
   dfs(id,0);
   cntt-=ans-1;

   if(k==2){
       while(f[id]){
           edge[f[id]].w=edge[f[id]^1].w=-1;
           id=edge[f[id]^1].to;
      }
       memset(v,0,sizeof(v)); ans=-INF;
       dp(1);
       cntt-=ans-1;
  }

   printf("%d\n",cntt);
   return 0;
}
/*
8 2
1 2
3 1
3 4
5 3
7 5
8 5
5 6

3 2
1 2
1 3
*/



posted @ 2022-02-26 23:35  fengzlj  阅读(73)  评论(0)    收藏  举报