A graph which is connected and acyclic can be considered a tree. The hight 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 (≤104) 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
#include<iostream>
#include<vector>
#include<queue>
#include<set>
using namespace std;
struct Node {
int num;
int floor;
};
vector<vector<int>>G; //图
vector<int>node;
int n;
set<int>s;
//并查集 findRoot() unions()
int findRoot(int i) {
while (node[i] != i) {
i = node[i];
}
return i;
}
void unions(int a,int b) {
int aRoot = findRoot(a);
int bRoot = findRoot(b);
if (aRoot != bRoot)
node[aRoot] = bRoot;
}
//第一次BFS找到所有叶子节点并加入集合s中
int findTreeRoot(vector<Node>nodes) {
queue<Node>q;
nodes[1].floor = 1;
q.push(nodes[1]);
int maxFloor = 1;
while(!q.empty()){
Node temp = q.front();
q.pop();
for (int i = 0;i < G[temp.num].size();i++) {
if (nodes[G[temp.num][i]].floor == 0) {
nodes[G[temp.num][i]].floor = temp.floor + 1;
q.push(nodes[G[temp.num][i]]);
maxFloor = temp.floor + 1;
}
}
}
int root = 1;
for (int i = 1;i <= n;i++) {
if (nodes[i].floor == maxFloor) {
root = i;
s.insert(i);
}
}
return root;
}
//第二次BFS找到所有叶子节点加入集合s中
void deepestRoot(vector<Node>nodes,int root) {
queue<Node>q;
nodes[root].floor = 1;
q.push(nodes[root]);
int maxFloor = 1;
while (!q.empty()) {
Node temp = q.front();
q.pop();
for (int i = 0;i < G[temp.num].size();i++) {
//如果该节点没有被访问过则更新该节点的信息
if (nodes[G[temp.num][i]].floor == 0) {
nodes[G[temp.num][i]].floor = temp.floor + 1;
q.push(nodes[G[temp.num][i]]);
maxFloor = temp.floor + 1;
}
}
}
//将最深的节点加入s中
for (int i = 1;i <= n;i++) {
if (nodes[i].floor == maxFloor) {
s.insert(i);
}
}
//输出结果
for (auto i = s.begin();i != s.end();i++) {
printf("%d\n", *i);
}
return;
}
int main() {
cin >> n;
G.resize(n + 1);
node.resize(n + 1, 0);
for (int i = 1;i <= n;i++)
node[i] = i;
//建立树
for (int i = 1;i <= n - 1;i++) {
int n1, n2;
scanf("%d%d", &n1, &n2);
G[n1].push_back(n2);
G[n2].push_back(n1);
unions(n1, n2);
}
int count = 0;//记录连通分量个数数
for (int i = 1;i <= n;i++) {
if (node[i] == i)
count++;
}
if(count==1){
vector<Node>ns(n + 1);
for (int i = 1;i <= n;i++) {
ns[i].num = i;
ns[i].floor = 0;
}
int root = findTreeRoot(ns);
deepestRoot(ns, root);
}
else {
printf("Error: %d components", count);
}
}
题目大意:给定一个图,先判断该图是否为树,如果是树则求出该树最深的叶子节点和根。
输入:第一行:N 该图的节点个数,从1~N;
第二行到第N行:N-1条边,每条边的端点。
思路:1.用set来存储结果。
2.先用并查集判断该图是否为树
3.如果是树则以节点1为根节点先用BFS找到最深的所有叶子节点并存储在set中(用DFS也可以)。
4.在以3中找到的叶子节点中的任意一个节点为根结点再用BFS找到最深的所有叶子节点存储在set中。
5.输出set中的节点即为所求结果。
注意:思路中的第三点,是将最深的说有叶子节点存储在set中(不是任意一个)。
例子:5
1 2
2 3
3 4
3 5