桃花一簇开无主,可爱深红映浅红。
——《题百叶桃花》
桃花长在桃树上,树的每个节点有一个桃花,调皮的HtBest想摘尽可能多的桃花。HtBest有一个魔法棒,摘到树上任意一条链上的所有桃花,由于HtBest法力有限,只能使用一次魔法棒,请求出Htbest最多可以摘到多少个桃花。
输入描述:
第一行有一个正整数n,表示桃树的节点个数。
接下来n-1行,第i行两个正整数ai,bi ,表示桃树上的节点ai,bi之间有一条边。
输出描述:
第一行一个整数,表示HtBest使用一次魔法棒最多可以摘到多少桃花。
示例1
输入
3
1 2
2 3
输出
3
示例2
输入
3
1 2
1 3
输出
3
示例3
输入
4
1 2
2 3
3 4
输出
4
备注:
对于100%的测试数据:
1 ≤ n ≤ 1000000
数据量较大,注意使用更快的输入输出方式。
思路:看完题以为是并查集,然而发现并不是,因为树枝是会分叉的,所以考虑其他方法。在数据结构专题里有一道题和该题很类似,是求树的直径,采用的是对树进行搜索。那么这道题就考虑用爆搜来解决了。联想以前尚未学习并查集时的想法-爆搜。用数组储存每个枝的情况,再一一搜索。这种搜一次的暴力用时900+ms或者是超时,如果搜2次,第一次处理一下,那时间就会大大缩减变成400+ms。另外,该题DFS,BFS都能做。
搜一次DFS代码:
#include<bits/stdc++.h>
using namespace std;
const int M=1e6+10;
int vis[M];
vector<int>p[M];
int ans;
int dfs(int x)
{
vis[x]=1;
int a=0,b=0;
for(int i=0;i<p[x].size();i++)//搜每个子分支的最长长度
{
int y=p[x][i];
if(vis[y]==0)
{
b=max(dfs(y),b);
if(b>a) swap(a,b);
}
}
ans=max(ans,a+b+1);
return a+1;
}
char c;
int val;
int Scan() { //输入外挂
int res = 0, flag = 0;
char ch;
if((ch = getchar()) == '-') flag = 1;
else if(ch >= '0' && ch <= '9') res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9')
res = res * 10 + (ch - '0');
return flag ? -res : res;
}
int main()
{
int n,l,r,i;
n=Scan();
for(i=1;i<=n-1;i++)
{
l=Scan();r=Scan();
p[l].push_back(r);
p[r].push_back(l);
}
dfs(1);
printf("%d\n",ans);
return 0;
}
搜2次DFS代码:
#include<cstdio>
#include<iostream>
using namespace std;
#include<cstring>
#include<algorithm>
const int maxn=1e7+5;
struct note{
int to,next;
} edge[maxn<<1];
int head[maxn],n,top;
int d[maxn];
inline void ADD(int u,int v) {
edge[top].to=v;
edge[top].next=head[u];
head[u]=top++;
edge[top].to=u;
edge[top].next=head[v];
head[v]=top++;
}
void dfs(int now,int fa,int dep)
{
d[now]=dep;
for(int i=head[now];~i;i=edge[i].next)
{
int to=edge[i].to;
if(to^fa)
{
dfs(to,now,dep+1);
}
}
}
int main()
{
while(~scanf("%d",&n))
{
top=0;
memset(head,-1,sizeof(head));
for(int i=1; i<n; ++i)
{
int u,v;
scanf("%d%d",&u,&v);
ADD(u,v);
}
dfs(1,-1,0);//找所有枝
int Max=0,pos=1;
for(int i=1;i<=n;++i)
{
if(Max<d[i])
{
pos=i,Max=d[i];
}
}//
dfs(pos,-1,0);//找最长枝
Max=0;
for(int i=1;i<=n;++i)
{
if(Max<d[i])
{
Max=d[i];
}
}
printf("%d\n",Max+1);
}
return 0;
}
附上大佬的搜2次BFS代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 1e9+7
using namespace std;
const int MAXN = 2000000;
const int MAXM = 2000000;
int n,m;
struct EDGE
{
int v,next,w;
}edge[MAXN];
int head[MAXN],e;
int q[MAXN],vis[MAXN],d[MAXN];
void init()
{
e=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)//链式前向星部分
{
edge[e].v=v;
edge[e].w=w;//权重
edge[e].next=head[u];//下一条边
head[u]=e++;//u为节点边的头节点
}
void bfs(int src)
{
for(int i=1;i<=n;i++)vis[i]=0,d[i]=INF;
int h=0,t=0;
q[t++]=src;
vis[src]=1;
d[src]=0;
while(h<t)
{
int u=q[h++];
for (int i=head[u];i!=-1;i=edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if (d[u]+w<d[v]){
d[v]=d[u]+w;
if (!vis[v])
{
q[t++]=v;
vis[v]=1;
}
}
}
}
}
int main(){
int u,v,w;
char k;
scanf("%d",&n);
init();
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
add(u,v,1);
add(v,u,1);
}
bfs(1);
int pos=-1,mx=-1;
for (int i=1;i<=n;i++)
if (d[i]>mx)
{
mx=d[i];
pos=i;
}
bfs(pos);
mx=-1;
for (int i=1;i<=n;i++)
if (d[i]>mx)mx=d[i];
printf("%d\n",mx+1);
return 0;
}