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 (≤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
超时代码 + 错误的判断题意。。
具体代码:
/**
内存超限
但是遇到几个粗心的错误,
1 . dfs 没有设置vis[max][max]数组 标记访问 导致了死循环
2. 多组数据输入时,没有重置vis数组
对于思维上的错误:
最开始的理解是 当 邻接表 edge[i].size为空时 就判断 最深的结点,理解错误,在无向图中 2 5 有边 , 5 2 也会
存在边 edge[i].size不会为空,
修改:
当每次for循环结束 就判断一次 高度,
**/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxsize = 1e4 + 5;
int n, hmax, to, from, set[maxsize];
vector<int> edge[maxsize], temp;
bool isTree = true, visit[maxsize], vis[maxsize][maxsize];
int find(int i){
return set[i] == i ? i : set[i] = find(set[i]);
}
void merge(int x, int y){
int faX = find(x);
int faY = find(y);
if(faX == faY){
isTree = false;
return;
}
set[faX] = faY;
}
void dfs(int u, int h){ //形成死循环的原因是每有将已经走过的点标记, 有向图可以设置为 visit[i][j]来表示 多组输入时,还需初始化vis数组
// cout << "u: " << u << endl;
// cout << edge[u].size() << endl;
for(int i = 0; i < edge[u].size(); i++){
if(!vis[u][edge[u][i]]){
vis[u][edge[u][i]] = vis[edge[u][i]][u] = true;
dfs(edge[u][i], h + 1);
}
}
// cout << "h : " << h << "hmax : " << hmax << endl;
if(h == hmax){
temp.push_back(u);
}else if(h > hmax){
hmax = h;
temp.clear();
temp.push_back(u);
}
}
void init(){
for(int i = 1; i <= n; i++){
set[i] = i;
for(int j = 1; j <= n; j++)
vis[i][j] = false;
}
}
int main(){
scanf("%d", &n);
init(); //初始化并查集
for(int i = 0; i < n - 1; i++){
if(!isTree)
break;
else{
scanf("%d%d", &from, &to);
merge(from, to);
edge[from].push_back(to);
edge[to].push_back(from);
}
}
if(isTree){
for(int i = 1; i <= n; i++){
init();//初始化vis数组
dfs(i, 1);
}
// cout << temp.size() << endl;
sort(temp.begin(), temp.end());
for(int i = 0; i < temp.size(); i++){
if(!visit[temp[i]]){
visit[temp[i]] = true;
printf("%d\n", temp[i]);
}
}
}else
printf("Error: K components\n");
return 0;
}
/**
本题题意:
给定n个结点(编号从1 - n) 给出 n - 1 条边,根据n - 1条边 需要求出 是否可以构建成一棵树(只有一个集合)(只存在一个强连通分量)
(最初的理解认为是 构建一棵树 是不能存在回路(In case that the given graph is not a tree, print “Error: K components”) 当不是一棵树
需要输出有几个强连通分量.
本题思路:
判断回路, (可以用并查集), 判断强连通分量的个数可以用并查集 也可以用dfs判断 ,无向图的dfs的 visit标记并不用设计出二维, 只用一维
就够用了,
1.找到一颗树的最深结点, 一开始的思路是 将每个结点当作顶点, 将每个结点作为起点, 判断树的最大高度 有多少个这样的起点,然后将这些点
装入一个 vector中 , 并排序, 但是此时需要去重, 直接使用一个vis数组进行标记, 输出过一次的元素就不用输出了 , 当然用set存储就不用进
行去重 和 排序的操作
2. 本题也存在更简单的思路:
任意从图中一个点进行遍历到最深的点集s 然后用s集合的其中一个点再次dfs 找到 最深的点集 s2, 此时s1, s2的并集就是最深的根
3.本题需要注意的是: 进行多次输入时 需要初始化判断的条件 . eg : visit[] 数组, temp数组(存放最深的root结点),
**/
#include<iostream>
#include<set>
#include<vector>
using namespace std;
const int maxsize = 1e4 + 5;
int n, hmax, floor, cnt, from, to;//temp 存放最深的root结点 floor为第一次dfs找到的最深结点 , cnt记录强连通分量的个数 (集合的个数)
vector<vector<int>> edge;
vector<int> temp;
set<int> s;
bool visit[maxsize];
void dfs(int u, int h){
visit[u] = true;
for(int i = 0; i < edge[u].size(); i++){
if(visit[edge[u][i]] == false)
dfs(edge[u][i], h + 1);
}
if(h > hmax){
temp.clear();
temp.push_back(u);
hmax = h;
}else if(h == hmax)
temp.push_back(u);
}
int main(){
scanf("%d", &n);
edge.resize(n + 1);
for(int i = 0; i < n - 1; i++){
scanf("%d%d", &from, &to);
edge[from].push_back(to);
edge[to].push_back(from);
}
for(int i = 1; i <= n; i++){
if(visit[i] == false){
dfs(i, 1);
cnt++;
if(temp.size() != 0)
floor = temp[0];
for(int j = 0; j < temp.size(); j++)
s.insert(temp[j]);
}
}
if(cnt >= 2)
printf("Error: %d components\n", cnt);
else{
temp.clear();
hmax = 0;
fill(visit + 1, visit + n + 1, false);
dfs(floor, 1);
for(int i = 0; i < temp.size(); i++){
s.insert(temp[i]);
}
for(auto it = s.begin(); it != s.end(); it++){
printf("%d\n", *it);
}
}
return 0;
}
本文探讨了一种算法,用于在给定的无向图中找到能够构成最高树的根节点,即所谓的最深根。文章详细解释了如何通过深度优先搜索(DFS)和并查集来解决这个问题,同时处理了可能存在的多个连通组件的情况。
236

被折叠的 条评论
为什么被折叠?



