PAT (Advanced Level) Practice - 1021 Deepest Root(25 分)

题目链接:点击打开链接

题目大意:给出一个无环图,求某个节点使得以它为根节点组成一棵树使得这棵树的深度达到最大。

解题思路:因为节点数大于 10000 而边数小于节点数是一个稀疏图,使用邻接矩阵存储的话内存会超限,所以选用邻接表存储,邻接表的话使用 vector 比较合适。判断是否连通由几部分组成时选用并查集,之后我使用 bfs 来搜索最深的节点。

AC 代码

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int maxn=10005;

int n, maxh;
int vis[maxn], dis[maxn], pre[maxn], h[maxn];
vector<int> vec[maxn];
queue<int> q;

void init()
{
    maxh=0;
    for(int i=1;i<=n;i++) pre[i]=i, vec[i].clear();
}

int findx(int x)
{
    return pre[x]==x?x:pre[x]=findx(pre[x]);
}

void join(int x, int y)
{
    int fx=findx(x), fy=findx(y);
    if(fx!=fy) pre[fx]=fy;
}

int bfs(int s)
{
    int ht=0;
    while(!q.empty()) q.pop();
    mem(vis,0); mem(dis,0);
    vis[s]=1;
    q.push(s);

    int u,k,j;
    while(!q.empty())
    {
        u=q.front(); q.pop();
        for(int i=0;i<vec[u].size();i++)
        {
            j=vec[u][i];
            if(!vis[j])
            {
                vis[j]=1;
                dis[j]=dis[u]+1;
                if(dis[j]>ht) ht=dis[j];
                q.push(j);
            }
        }
    }

    if(ht>maxh) maxh=ht;

    return ht;
}

int main()
{
    while(~scanf("%d",&n))
    {
        init();
        int u,v;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            vec[u].push_back(v);
            vec[v].push_back(u);
            join(u,v);
        }

        int comp=0;
        for(int i=1;i<=n;i++)
            if(pre[i]==i) comp++;

        if(comp>1) printf("Error: %d components\n",comp);
        else
        {
            for(int i=1;i<=n;i++) h[i]=bfs(i);
            for(int i=1;i<=n;i++)
                if(maxh==h[i]) printf("%d\n",i);
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/81357469