1021 Deepest Root (25 分) 测试点1是n=1 惊不惊喜

1021 Deepest Root (25 分)

A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤10​4​​) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each describes an edge by given the two adjacent nodes' numbers.

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print Error: K components where K is the number of connected components in the graph.

Sample Input 1:

5
1 2
1 3
1 4
2 5

Sample Output 1:

3
4
5

Sample Input 2:

5
1 3
1 4
2 5
3 4

Sample Output 2:

Error: 2 components

这个题思路:

先使用并查集搞定是否有多个连通分量,如果 只有一个连通分量,那就找最远路径的点。

本来我的想法是每个元素进行一次深度搜索,看看从这个元素出发,最深路径有多远,结果是超时,说明一定有更简单思想。

查了查发现大家都是用的下面这种算法:

第一步 任意选择一个结点,从这个结点出发,找到最远的结点(有几个算几个)

第二步 再从最远结点中任意选择一个结点,从该结点出发,再次寻找最远结点,两次寻找的结果的并集就是所求的结果。

最后的证明 最能说服我的是牛客一个老哥写的:http://m.nowcoder.com/questionTerminal?uuid=f793ad2e0c7344efa8b6c18d10d4b67b

整体思路就是,因为n个结点n-1个边,如果有环肯定不是一个联通分量。所以如果是一个联通分量肯定是没环的。那么特殊情况就是有分叉。比如1-2-3-4-5  并且3-6。相当于3链接了4又连接6,但是最长路径应该是1-2-3-4-5 ,3-6只是个分叉。那么以分叉结点作为定位点,在分叉结点3 右边的,距离1肯定最远,在分叉结点左边的,距离5肯定最远(因为分叉的长度肯定没有从主路径一段到分叉结点长度长,否则他就不是分叉了,而是主路径了)。而分叉结点上的结点,也肯定到主路径某一端最长。所以,从任意结点开始搜索,必定能够找到一个最深的结点。而从这个最深的结点再次开始,必定能够找到其他最深的结点。其实如果出现多个最深结点,他们关系应该类似于    1-2-3  2-4. 1 3 4地位相等。

代码没这么优化,有点乱,太懒了我

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <hash_set>
    #include <set>
    #include <queue>
    using namespace std;
    int pre[10001];
    int Find(int x)
    {
        int r=x;
    //寻找老大 最差就是自己就是老大了   
        while(r!=pre[r])
            r=pre[r];

    //把寻找路径上所有结点老大固定为一个最后寻找到的老大结点
    //下面一步也称之为路径压缩
        int i=x,j;
        while(pre[i]!=r)
        {
            j=pre[i];
            pre[i]=r;
            i=j;
        }
        return r;
    }
    void mix(int x,int y)//合并
    {
        int fx=Find(x),fy=Find(y);
        if(fx!=fy)
        {
            pre[fy]=fx;
        }
    }

    int main()
    {

        int n;
        cin>>n;
        int a[n+1]= {0};
        int b[n+1]= {0};
        for(int i=1; i<n; i++)
            pre[i]=i;
        for(int i=1; i<n; i++)
        {
            cin>>a[i]>>b[i];
            mix(a[i],b[i]);
        }
        for(int q=1; q<=n; q++)
            Find(q);
        set<int> ss;
        for(int i=1; i<=n; i++)
        {
            ss.insert(pre[i]);
        }
        if(ss.size()>1)
            cout<<"Error: "<<ss.size()<<" components";
        else if(n==1)
            cout<<'1';
        else if(n>1)
        {
    //还是有问题
            int visit[n+1];
            int sign[n+1];
            fill(visit,visit+n+1,0);
            fill(sign,sign+n+1,0);
            int time=1;

            queue<int> que;
            que.push(1);
            
            que.push(-1);
            visit[1]=1;
            int maxx=-1;

            while(que.size()!=0)
            {
                int start=que.front();
                if(start==-1){
                    time++;
                    que.pop();
                    if(que.size()==0)
                        break;
                    start=que.front();
                    que.push(-1);
                }

                que.pop();

                for(int i=1; i<n; i++)
                {
                    if(a[i]==start&&visit[b[i]]==0)
                    {
                        que.push(b[i]);
                        visit[b[i]]=1;
                        sign[b[i]]=time;
                        if(maxx<time)
                            maxx=time;
                    }
                    if(b[i]==start&&visit[a[i]]==0)
                    {
                        que.push(a[i]);
                        visit[a[i]]=1;
                        sign[a[i]]=time;
                        if(maxx<time)
                            maxx=time;
                    }
                }
            }
            set<int> sett;
            for(int i=1; i<=n; i++)
            {
                if(sign[i]==maxx)
                {
                    sett.insert(i);
                }
            }

            //第二次
            fill(visit,visit+n+1,0);
            fill(sign,sign+n+1,0);
            maxx=-1;
            time=1;
            que.push(*sett.begin());
            visit[*sett.begin()]=1;
            que.push(-1);
            while(que.size()!=0)
            {
                int start=que.front();
                if(start==-1){
                    time++;
                    que.pop();
                    if(que.size()==0)
                        break;
                    start=que.front();
                    que.push(-1);
                }
                que.pop();
                for(int i=1; i<n; i++)
                {
                    if(a[i]==start&&visit[b[i]]==0)
                    {
                        que.push(b[i]);
                        visit[b[i]]=1;
                        sign[b[i]]=time;
                        if(maxx<time)
                            maxx=time;
                    }
                    if(b[i]==start&&visit[a[i]]==0)
                    {
                        que.push(a[i]);
                        visit[a[i]]=1;
                        sign[a[i]]=time;
                        if(maxx<time)
                            maxx=time;
                    }
                }
            }
            for(int i=1; i<=n; i++)
            {
                if(sign[i]==maxx)
                {
                    sett.insert(i);
                }
            }



            set<int>::iterator it;
            vector<int> out;
            for(it=sett.begin(); it!=sett.end(); it++)
            {
                out.push_back(*it);
            }
            sort(out.begin(),out.end());
            int first=1;
            for(int i=0; i<out.size(); i++)
            {
                if(first==1)
                {
                    cout<<out[i];
                    first=0;
                }
                else
                    cout<<endl<<out[i];
            }

        }
        return 0;
    }

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值