http://pat.zju.edu.cn/contests/pat-practise/1021

时间限制
1500 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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.用邻接矩阵会超内存的,所以改用邻接表;
2.并查集合并的时候记住是要合并父亲,这点疏忽就不好了;
3.一开始枚举所有点进行dfs,最后一个点会超时,后来的思路是先随意取一个点进行bfs,找到离这个点最远的点加入集合,再对这个点进行bfs,就得到了所有的点。
然后同一个点可能会被加入两次,所以最后输出的时候要去重。

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <algorithm>  
  4. #include <memory.h>  
  5. #include <cstdio>  
  6. #include <cstdlib>  
  7. #include <set>  
  8. #include <vector>  
  9. #include <queue>  
  10. using namespace std;  
  11. #define MAX 0Xfffffff  
  12. int dis[10001];  
  13. int n;  
  14. vector<int> map[10001];//邻接表  
  15. int father[10001];  
  16. int visit[10001];  
  17. vector<int> ans;  
  18. int getfather(int i){  
  19.     if(i==father[i])  
  20.         return i;  
  21.     return father[i] = getfather(father[i]);  
  22. }  
  23. void unionmerge(int i, int j){  
  24.     father[i] = j;  
  25. }  
  26. int bfs(int x){  
  27.     queue<int> q;  
  28.     memset(visit, 0, sizeof(visit));  
  29.     visit[x] = 1;  
  30.     int maxv = 0;  
  31.     q.push(x);  
  32.     while(!q.empty()){  
  33.         int v = q.front();  
  34.         q.pop();  
  35.         if(dis[v]>maxv)  
  36.             maxv = dis[v];  
  37.         for(int i=0;i<map[v].size();++i)  
  38.             if(!visit[map[v][i]]){  
  39.                 visit[map[v][i]] = 1;  
  40.                 dis[map[v][i]] = dis[v] + 1;  
  41.                 q.push(map[v][i]);  
  42.             }  
  43.     }  
  44.     return maxv;  
  45.       
  46. }  
  47. int main(){  
  48.   
  49.     //freopen("in.txt", "r", stdin);  
  50.       
  51.     int a, b;  
  52.     cin>>n;  
  53.     for(int i=1;i<=n;++i)  
  54.         father[i] = i;  
  55.     for(int i=0;i<n-1;++i){  
  56.         scanf("%d%d", &a, &b);  
  57.         map[a].push_back(b);  
  58.         map[b].push_back(a);  
  59.         unionmerge(getfather(a), getfather(b)); //getfather合并  
  60.     }  
  61.     set<int> ss;  
  62.     for(int i=1;i<=n;++i){  
  63.         int f = getfather(i);  
  64.         if(ss.count(f)<=0){  
  65.             ss.insert(f);  
  66.         }  
  67.     }  
  68.     if(ss.size()!=1){  
  69.         printf("Error: %d components\n", ss.size());  
  70.     }else{  
  71.       
  72.         int maxv = bfs(1);  
  73.         for(int i=1;i<=n;++i){  
  74.             if(dis[i]==maxv)  
  75.                 ans.push_back(i);  
  76.         }  
  77.         maxv = bfs(ans[0]);  
  78.         for(int i=1;i<=n;++i){  
  79.             if(dis[i]==maxv)  
  80.                 ans.push_back(i);  
  81.         }  
  82.           
  83.         sort(ans.begin(), ans.end());  
  84.         printf("%d\n", ans[0]);  
  85.         //去掉重复的  
  86.         for(int i=1;i<ans.size();++i)  
  87.             if(ans[i]!=ans[i-1])  
  88.                 printf("%d\n", ans[i]);  
  89.     }  
  90.       
  91.     //fclose(stdin);  
  92. }     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值