CF1294F Three Paths on a Tree
CF1294F Three Paths on a Tree
题意翻译
给定一棵含 n\ (3\leq n\leq2\cdot 10^5)n (3≤n≤2⋅105) 个结点的无权树,试找出三个结点 uu、vv、ww,\operatorname{s.t.}s.t.
\operatorname{card}({u,v\text{ 间的路径}}\cup{v,w\text{ 间的路径}}\cup{w,u\text{ 间的路径}})card({u,v 间的路径}∪{v,w 间的路径}∪{w,u 间的路径})
最大。
你需要输出两行:
第一行为 \max\operatorname{card}({u,v\text{ 间的路径}}\cup{v,w\text{ 间的路径}}\cup{w,u\text{ 间的路径}})maxcard({u,v 间的路径}∪{v,w 间的路径}∪{w,u 间的路径})
第二行三个整数,即 uu、vv、ww,如有多种答案,输出一种即可。
题解:
贪心+树。
首先简单想一想能发现:答案应该是树的直径加上所有不在直径上的节点中,距离直径最长的距离。
那么只需要模拟这个过程就可以:
先两次DFS求出树的直径(记录路径长和两个端点),然后把直径上所有节点打上标记,然后枚举所有非直径上的节点,更新最大距离,就可以过了。
复杂度是级别。
代码:
#include<cstdio>
using namespace std;
const int maxn=2e5+5;
int n;
int tot,head[maxn],nxt[maxn<<1],to[maxn<<1];
int maxx,pos[4],ans;
int deep[maxn],fa[maxn];
bool v[maxn];
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs(int x,int f,int p)
{
if(p==2)
fa[x]=f;
deep[x]=deep[f]+1;
if(deep[x]>maxx)
{
maxx=deep[x];
pos[p]=x;
}
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)
continue;
dfs(y,x,p);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
deep[0]=-1;
dfs(1,0,1);
maxx=0;
dfs(pos[1],0,2);
int x=pos[2];
while(x)
{
v[x]=1;
x=fa[x];
}
ans+=maxx;
maxx=0;
int tmp=0;
for(int i=1;i<=n;i++)
{
if(v[i])
continue;
else
{
x=i;
tmp=0;
while(!v[x])
{
x=fa[x];
tmp++;
}
if(maxx<tmp)
{
maxx=tmp;
pos[3]=i;
}
}
}
if(!maxx)
for(int i=1;i<=n;i++)
if(v[i]&&i!=pos[1]&&i!=pos[2])
{
pos[3]=i;
break;
}
ans+=maxx;
printf("%d\n%d %d %d\n",ans,pos[1],pos[2],pos[3]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架