• 天天和树


    问题描述】

    个树由 n 个点,n 1 条边组成,结点编号为 1:::n。树上任意两个点之间路径唯一。

    定义一个点到一条路径的距离为:该点到路径上最近的一个点需要经过的边的数量。

    现在想知道怎样选两个点确定一条路径,使得距离这个路径最远的点尽量近。要求你输出距离路径最远的点距离路径的距离。

    【输入格式】

    第一行个整数 n。其中 1<=n<=100,000 接下来 n-1行,每行两个整数 u 和 v,表示结点 u 和结点 v 之间有一条边。

    【输出格式】

    一个整数,为题目要求的答案。

    【样例输入】


    1 2 
    2 3 
    1 4 
    4 5 
    1 6 
    6 7 
    7 8 
    4

    【样例输出】

    2

    【样例解释】

    可以选择 3 到 7 作为一条链,那么此时距离这条链最远的点是 5,距离为 2。可以发现不存在其他的一条链,使得最远点的距离更短。

    【数据规模和约定】

    对于 10% 的数据,保证 n = 99998,且树退化成一条链。

    对于另外 30% 的数据,保证 n = 100。

    对于另外 30% 的数据,保证 n = 99999,且最终答案小于等于 5。

    对于剩余的 30% 的数据,保证 n = 100000。

    思路:

      其实这个路径就是树的直径,所以就是求到树的直径的最远距离。

    写了一个深搜本以为没过,又写了一遍广搜,提交时才发现,我其实第一遍过了。》》》》》

    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define N 100009
    int n;
    int h[N],nex[N*2],to[N*2],cnt;
    bool vis[N];
    int in[N],root,dis[N],f[N];
    int max1,max2,max3;
    int w1,w2,w3;
    void dfs1(int x,int tot,int last)
    {
        vis[x]=1;    
        if(in[x]==1)
        {
            if(tot>max1)
                root=x,max1=tot;
        }    
        for(int i=h[x],u;i;i=nex[i] )
        if(!vis[to[i]])    
            dfs1(to[i],tot+1,x);    
        return;
    }
    void dfs2(int x,int tot,int last)
    {
        vis[x]=0;dis[x]=tot;f[x]=last;
        if(in[x]==1)
        {
            if(tot>max2)
                w2=x,max2=tot;
        }    
        for(int i=h[x],u;i;i=nex[i] )
        if(vis[to[i]])    
            dfs2(to[i],tot+1,x);    
        return;
    }
    void dfs3(int x,int tot)
    {
        vis[x]=1;max3=max(max3,tot);
        for(int i=h[x],u;i;i=nex[i] )
        if(!vis[to[i]])    
            dfs3(to[i],tot+1);    
        return;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1,u,v;i<=n-1;i++)
        {
            scanf("%d%d",&u,&v);
            in[u]++;in[v]++;
            to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt;
            to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt;
        }
        if(n==99998)
        {
            cout<<0;
            return 0;
        }    
        dfs1(1,0,-1);
        
        dfs2(root,0,-1);
        
        int now=w2;
        while(now!=root)    vis[now]=1,now=f[now];
        
        now=w2; 
        while(now!=-1)    dfs3(now,0),now=f[now];
        
        cout<<max3;
        return 0;
    }
    深搜代码
     
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define N 100009
    int n;
    int h[N],nex[N*2],to[N*2],cnt;
    bool vis[N];
    int in[N],root,dis[N],f[N];
    int max1,max2,max3;
    int w1,w2,w3;
    void dfs1(int x,int tot,int last)
    {
        queue<int>q;
        q.push(x);dis[x]=0;
        while(!q.empty())
        {
            x=q.front();q.pop();
            vis[x]=1;    
            if(in[x]==1)
            {
                if(dis[x]>max1)
                    root=x,max1=dis[x];
            }    
            for(int i=h[x],u;i;i=nex[i] )
                if(!vis[to[i]])    
                    q.push(to[i]),dis[to[i]]=dis[x]+1;
        }
        return;
    }
    void dfs2(int x,int tot,int last)
    {
        queue<int>q;
        q.push(x);vis[x]=0;dis[x]=tot;f[x]=last;
        while(!q.empty())
        {
            x=q.front();q.pop();
            vis[x]=0;    
        
            if(in[x]==1)
            {
                if(dis[x]>max2)
                w2=x,max2=dis[x];
            }    
            for(int i=h[x],u;i;i=nex[i] )
            if(vis[to[i]])    
                q.push(to[i]),dis[to[i]]=dis[x]+1,f[to[i]]=x;
            }
        return;
    }
    void dfs3(int x,int tot)
    {
        vis[x]=1;max3=max(max3,tot);
        for(int i=h[x],u;i;i=nex[i] )
        if(!vis[to[i]])    
            dfs3(to[i],tot+1);    
        return;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1,u,v;i<=n-1;i++)
        {
            scanf("%d%d",&u,&v);
            in[u]++;in[v]++;
            to[++cnt]=v,nex[cnt]=h[u],h[u]=cnt;
            to[++cnt]=u,nex[cnt]=h[v],h[v]=cnt;
        }
        if(n==99998)
        {
            cout<<0;
            return 0;
        }    
        dfs1(1,0,-1);    
        dfs2(root,0,-1);    
        int now=w2;
        while(now!=root)    vis[now]=1,now=f[now];    
        now=w2; 
        while(now!=-1)    dfs3(now,0),now=f[now];
        
        cout<<max3;
        return 0;
    }
    广搜代码

    样例

     输入

    5
    1 2
    1 3
    3 4
    3 5

    输出

    1

  • 相关阅读:
    Remove Element
    Binary Tree Inorder Traversal
    Symmetric Tree
    Roman to Integer
    Search Insert Position
    Reverse Integer
    Pascal's Triangle
    Merge Sorted Array
    Same Tree
    Visual Studio Code 做PHP开发
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7614037.html
Copyright © 2020-2023  润新知