zoukankan      html  css  js  c++  java
  • 浙大pat甲级题目---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 (<=10000) 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
    

     题目大意:就是让比较一颗树的最大高度所对应的跟节点,如果有其他联通分支就输出联通分支数。

    题解:这道题由两部分,第一部分是求得图的联通分支数,如果大于一就输出个数。第二部分是如果联通分支数等于1就要寻找每一个顶点所对应的树高,并输出最大的树高所对应的节点。

    针对第一部分,我们使用并查集的概念去做(基本是固定套路),对于什么是并查集,并查集怎么用,我是参考的这篇博客,写的非常有意思,大家可以研究:

    http://blog.csdn.net/u013546077/article/details/64509038

    这里不做太多赘述。

    针对第二部分,这里选用dfs得到每个顶点的最短路径

    #include <iostream>
    #include<vector>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAX 100001
    using namespace std;
    //并查集解决联通分之数的问题,dfs解决最高树问题
    int a[MAX];//并查集
    vector<int>graph[MAX];//学会用这种方式表达图的临街表
    vector<int>result;//存放最后输出结果的
    int visit[MAX];
    int length[MAX];//存放每个节点的最深长度
    void init(int n)//并查集初始化
    {
        for(int i=1;i<=n;i++)
        {
            a[i]=i;
        }
    }
    int find(int i)//查找i的根节点,且带路径压缩。目前看到最短版本
    {
        if(a[i]!=i)//当他的根不是自己(即还没找到根)
            a[i]=find(a[i]);//递归的寻找父亲
        return a[i];
    }
    void join(int i,int j)//节点i和j连接在一起
    {
        int x=find(i);
        int y=find(j);
        if(x!=y)
            a[x]=y;//联通两个分之
    }
    int dfs(int i)//以i为根,返回最大深度
    {
        int ans=0;
        int num=(int)graph[i].size();
        if(visit[i]==1)//叶子节点
            return 0;
        visit[i]=1;
        for(int j=0;j<num;j++)
        {
    
            int next=graph[i][j];
            if(visit[next]!=1)
            {
                 int deep=dfs(next);
                ans=max(deep,ans);
    
            }
        }
        return ans+1;
    }
    
    int main() {
        int n;
        int count=0;
        int max=-1;
        int index=0;
        scanf("%d",&n);
        init(n);
    
        for(int i=1;i<n;i++)//学会这种写临界表的方式
        {
            int x,y;
            scanf("%d%d",&x,&y);
            join(x,y);
            //将两者相连
            graph[x].push_back(y);
            graph[y].push_back(x);
        }
        for(int i=1;i<=n;i++)
        {
            if(a[i]==i)//当发现一个根的时候,联通分之数加一
                count++;
        }
        if(count!=1)
        {
            printf("Error: %d components
    ",count);
        }
        else
        {
            for(int i=1;i<=n;i++)
            {
                memset(visit,0, sizeof(visit));//注意每一次都要清空
                length[i]=dfs(i);
            }
            for(int i=1;i<=n;i++)//当题目中要求 输出很多相同大小的数的索引的时候,学会这种方法
            {
                if(length[i]>max)
                {
                    max=length[i];
                    index=i;
                }
            }
            for(int i=1;i<=n;i++)
            {
                if(length[i]==length[index])//很巧妙,相当于记下来最大的数,再循环
                    printf("%d
    ",i);
            }
    
        }
        return 0;
    }
  • 相关阅读:
    CF869E The Untended Antiquity 解题报告
    Walk 解题报告
    CF911F Tree Destruction 解题报告
    P4397 [JLOI2014]聪明的燕姿
    洛谷 P2329 [SCOI2005]栅栏 解题报告
    洛谷 P3747 [六省联考2017]相逢是问候 解题报告
    set-erase
    set-empty
    set-empty
    set-end
  • 原文地址:https://www.cnblogs.com/SK1997/p/8588527.html
Copyright © 2011-2022 走看看