图的遍历 pat 1021

#include <iostream>
#include<vector>
#include<algorithm>
//1021,bfs
using namespace std;
const int N  = 1e4+5;
int fa[N];
vector<int> G[N];//邻接表
vector<int> t, ans;

int findFa(int x){
       int a=x;
       while(x!=fa[x]){
              x=fa[x];
       }
       while(a!=fa[a]){
              int z = a;
              a=fa[a];
              fa[z] = x;
       }
       return x;
}

void Union(int a, int b){
       int faA = findFa(a);
       int faB = findFa(b);
       if(faA != faB)
              fa[faA] = faB;
}
int isRoot[N]={0};
int calBlock(int n){
       int num =0;
       for(int i = 1; i <= n;i++){
              isRoot[findFa(i)] = 1;
       }
       for(int i = 1; i <= n;i++){
              num+=isRoot[i];
       }
       return num;
}
int maxH = 0;
void dfs(int u, int height, int pre){
       if(height>maxH){//插入口,也就是边界条件,不是的话就继续递归
              maxH = height;
              t.clear();
              t.push_back(u);
       }else if(height == maxH) t.push_back(u);
              // 不加return 因为1 要重复查找, 2 执行到没办法执行,那么也就自动结束这个函数了
       for(int i = 0; i < G[u].size();i++){
              if(G[u][i] == pre) continue;//跳过回头的//因为邻接表不能删除,而假如用 邻接矩阵
                                          //可以另G[u][i] = G[i][u] = 0;
              dfs(G[u][i],height+1,u);
       }
}



int main()
{
       freopen("1021.txt","r",stdin);
      int n;
      cin>>n;//节点从1开始
      for(int i  = 1; i <=n;i++){
       fa[i] = i;
      }
      int m = n-1,a,b;
      while(m--){
       cin>>a>>b;
       G[a].push_back(b);
       G[b].push_back(a);
       Union(a,b);
      }
      int numBlocks = calBlock(n);
      if(numBlocks != 1)
              printf("Error: %d components\n",numBlocks);
      else{
              dfs(1,1,-1);
              ans = t;
              dfs(ans[0],1,-1);//从 ans[0]开始找最远的,加上第一次找的就是全部最远的
              for(int i = 0; i < t.size();i++){
                     ans.push_back(t[i]);
              }

              sort(ans.begin(),ans.end());
              printf("%d\n",ans[0]);
              for(int i = 1; i < ans.size();i++){
                     if(ans[i]!=ans[i-1])//防止重复
                            printf("%d\n",ans[i]);
              }
      }

    //cout << "Hello world!" << endl;
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值