数的直径(两次DFS)

题目传送门

桃花

题目描述

    桃花一簇开无主,可爱深红映浅红。

                                        ——《题百叶桃花》

    桃花长在桃树上,树的每个节点有一个桃花,调皮的HtBest想摘尽可能多的桃花。HtBest有一个魔法棒,摘到树上任意一条链上的所有桃花,由于HtBest法力有限,只能使用一次魔法棒,请求出Htbest最多可以摘到多少个桃花。

输入描述:

第一行有一个正整数n,表示桃树的节点个数。
接下来n-1行,第i行两个正整数a,b

输出描述:

第一行一个整数,表示HtBest使用一次魔法棒最多可以摘到多少桃花。
输入
3
1 2
2 3
输出
3
题意:就是求数的直径,不过本题求的是顶点数,树的直径的一个性质:距某个点最远的叶子节点一定
是树的某一条直径的端点。这样我们先dfs求一个点的最远端点,再从这个点dfs一次。也可以百度一下,
大意是反证距离任意点最远的点都是直径的端点。
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> PII;
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
//head
#define N 1000005
vector<int>V[N];
int dis[N];
int xp=-1;
int ans=0;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
void dfs(int a)
{
    if(xp<dis[a])
    {
        xp=dis[a];
        ans=a;
    }
    for(int v: V[a])
    {
        if(dis[v]==-1)
        {
            dis[v]=dis[a]+1;
            dfs(v);
        }
    }
}
int main()
{
    //ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    int a,b;
    n=read();
    for(int i=0;i<n-1;i++)
    {
       a=read();
       b=read();
       V[a].pb(b);
       V[b].pb(a);
    }
   for(int i=1;i<=n;i++) dis[i]=-1;
   dis[1]=0;
   dfs(1);
   memset(dis,-1,sizeof(dis));
   dis[ans]=0;
   xp=-1;
   dfs(ans);
   write(xp+1);
}

 

posted @ 2018-08-25 21:21  better46  阅读(674)  评论(0编辑  收藏  举报