2 条题解

  • 0
    @ 2026-2-15 9:55:45

    树的直径,几乎板子题,用一遍dfs找寻起始点和长度,两次dfs建立重链,LCA求出起始点最近公共祖先,往上枚举,输出,完事。

    注意:十年OI一场空,____________。

    重链LCA直通连接

    AC 代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=5e5+10;
    vector<pair<int,int> >G[N];
    int d[N],d2[N],n,ans,st,ed,s[N],s2[N];
    //d表示当前节点往下的最长路径长度,s存储终点
    //d2和s2表示次长路径
    //ans,st,ed存储全树最长路径及其起始点 
    int son[N],siz[N],tp[N],fa[N],dep[N];
    void dfs(int x,int xfa,int dis)//找寻直径长度并存储起始点 
    {
    	s[x]=s2[x]=x;
    	for(auto i:G[x])if(i.first!=xfa)
    	{ 
    		dfs(i.first,x,dis+i.second);
    		int t=d[i.first]+i.second;
    		if(t>d[x])d2[x]=d[x],s2[x]=s[x],d[x]=t,s[x]=s[i.first];
    		else if(t>d2[x])d2[x]=t,s2[x]=s[i.first];//更新 
    	}
    	if(d[x]+d2[x]>ans)ans=d[x]+d2[x],st=s[x],ed=s2[x];
    	if(d[x]+dis>ans)ans=d[x]+dis,st=s[x],ed=1;//不要忘记往上的路径长度 
    }
    void dfs1(int x,int xfa)//重链LCA 
    {
    	siz[x]=1;son[x]=-1;fa[x]=xfa;dep[x]=dep[xfa]+1;
    	for(auto i:G[x])if(i.first!=xfa)
    	{
    		dfs1(i.first,x);
    		siz[x]+=siz[i.first];
    		if(siz[i.first]>siz[son[x]]||son[x]==-1)son[x]=i.first;
    	}
    }
    void dfs2(int x,int top)
    {
    	tp[x]=top;
    	if(son[x]!=-1)dfs2(son[x],top);
    	for(auto i:G[x])if(i.first!=fa[x]&&i.first!=son[x])dfs2(i.first,i.first);
    }
    int LCA(int x,int y)
    {
    	for(;tp[x]!=tp[y];x=fa[tp[x]])if(dep[tp[x]]<dep[tp[y]])swap(x,y);
    	return dep[x]<dep[y]?x:y; 
    }
    signed main()
    {
    	scanf("%lld",&n);
    	for(int i=1,x,y,w;i<n;i++)
    	{
    		scanf("%lld%lld%lld",&x,&y,&w);x++,y++;
    		G[x].push_back({y,w});
    		G[y].push_back({x,w});
    	}
    	dfs(1,0,0);
    	printf("%lld ",ans);
    	dfs1(1,0);dfs2(1,1);
    	int lca=LCA(st,ed);
    	vector<int>up1,up2;//记录答案 
    	for(;st!=lca;st=fa[st])up1.push_back(st);
    	up1.push_back(lca);//不能忘lca 
    	for(;ed!=lca;ed=fa[ed])up2.push_back(ed);
    	reverse(up2.begin(),up2.end());//反过来才是答案 
    	printf("%lld\n",up1.size()+up2.size());
    	for(int i:up1)printf("%lld ",i-1);
    	for(int i:up2)printf("%lld ",i-1);//输出 
    	return 0;//完结撒花
    }
    
    • 0
      @ 2025-12-9 18:01:23
      #include<bits/stdc++.h>
      using namespace std;
      const int N=5e5+10;
      #define int long long
      #define PII pair<int,int>
      #define fi first
      #define se second
      int mx[N],mx1[N],mx2[N],son1[N],son2[N],rt[N];
      vector<PII>G[N];
      void dfs(int x,int f)
      {
      	for(auto i:G[x])if(i.fi!=f)
      	{
      		int y=i.fi,w=i.se;
      		dfs(y,x);
      		if(mx1[x]<mx1[y]+w)
      			mx2[x]=mx1[x],mx1[x]=mx1[y]+w,son2[x]=son1[x],son1[x]=y;
      		else if(mx2[x]<mx1[y]+w)
      			mx2[x]=mx1[y]+w,son2[x]=y;
      		if(mx[x]<mx[y])
      			mx[x]=mx[y],rt[x]=rt[y];
      	}
      	if(mx[x]<=mx1[x]+mx2[x])
      		mx[x]=mx1[x]+mx2[x],rt[x]=x;
      }
      deque<int>q;
      void dfs1(int x)
      {
      	q.push_back(x);
      	if(son1[x])dfs1(son1[x]);
      }
      void dfs2(int x)
      {
      	if(son1[x])dfs2(son1[x]);
      	q.push_back(x);
      }
      void output(int x)
      {
      	cout<<mx[x]<<' ';
      	if(son1[x])dfs2(son1[x]);
      	q.push_back(x);
      	if(son2[x])dfs1(son2[x]);
      	cout<<q.size()<<'\n';
      	for(int i:q)cout<<i-1<<' ';
      }
      signed main()
      {
      	int n;cin>>n;
      	for(int i=1;i<n;i++)
      	{
      		int x,y,w;cin>>x>>y>>w;x++,y++;
      		G[x].push_back({y,w});
      		G[y].push_back({x,w});
      	}
      	dfs(1,0);
      	output(rt[1]);
      	return 0;
      }
      
      • 1

      信息

      ID
      8195
      时间
      500ms
      内存
      1024MiB
      难度
      5
      标签
      递交数
      25
      已通过
      13
      上传者