一个连接和非循环的图可以被认为是一棵树。树的高度取决于选定的根。现在,你应该找到导致最高树的根。这样的根被称为最深的根。
Input Specification:
每个输入文件包含一个测试案例。对于每个案例,第一行包含一个正整数N(≤10^4 ),这是节点的数量,因此节点的编号从1到N。然后是N-1行,每行描述一条边,给出相邻两个节点的编号。
Output Specification:
对于每个测试案例,在一行中打印每个最深的根。如果这样的根不是唯一的,则按其数字的递增顺序打印。如果给定的图不是一棵树,则打印Error。K组件,其中K是图中连接组件的数量。
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
题目传送门https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805482919673856
题目大意:使用给定数据建立一个无向图,判断该图是否连通图,如果不是,输出器联通分量的数目;如果是连通图,则从图每个结点出发遍历该图,并找出以该结点为起点的路径长度最长的结点,最后把所有的结点输出。
解析:本题两个做法
做法1:图的最深根问题,本题分两步完成;step1:先对图amg的结点为起点进行dfs,求出cnt的大小,如果cnt>1,则输出cnt;则step2:再对图amg的每个结点为起点进行dfs,用vecto<int>temp存储该结点的最深根们,每完成一个点的dfs,则将vector<int>temp的数据存入map<int>answer中,最后输出map<int>answer.
做法2:做法1的step1基本不变只在给结点dfs时记录一个最深根,step2:只以该结点为起点进行dfs其他做法与做法1step2相同。
c站上找的证明(下图内容)
做法1:(测试点3过不了,在网上查了一下,别的博主说bfs也过不了)
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
int n,visit[10010],amg[10010][10010];
set<int> answer;
vector<int>temp;
void dfs1(int a) {
visit[a] = 1;
for (int i = 1; i <= n; i++) {
if (visit[i] == 0 && amg[a][i] == 1) {
dfs1(i);
}
}
}
int max_deep=-1, depth;
void dfs2(int a,int depth) {
visit[a] = 1;
if (depth > max_deep) {
max_deep = depth;
temp.clear();
temp.push_back(a);
}
else if (depth == max_deep) {
temp.push_back(a);
}
for (int i = 1; i <= n; i++) {
if (visit[i] == 0 && amg[a][i] == 1) {
dfs2(i,depth+1);
}
}
}
int main() {
int cnt = 0;
cin >> n;
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
amg[a][b] = amg[b][a] = 1;
}
for (int i = 1; i <= n; i++) {
if (visit[i] == 0) {
dfs1(i);
cnt++;
}
}
if (cnt != 1) {
cout << "Error: " << cnt << " components";
return 0;
}
for (int i = 1; i <= n; i++) {
fill(visit, visit + 10010, 0);
max_deep = -1;
dfs2(i, 0);
for (int i = 0; i < temp.size(); i++) {
answer.insert(temp[i]);
}
temp.clear();
}
for (auto it = answer.begin(); it != answer.end(); it++) {
cout << *it << endl;
}
return 0;
}
做法2:柳神代码 柳神c站原帖
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
int n, maxheight = 0;
vector<vector<int>> v;
bool visit[10010];
set<int> s;
vector<int> temp;
void dfs(int node, int height) {
if(height > maxheight) {
temp.clear();
temp.push_back(node);
maxheight = height;
} else if(height == maxheight){
temp.push_back(node);
}
visit[node] = true;
for(int i = 0; i < v[node].size(); i++) {
if(visit[v[node][i]] == false)
dfs(v[node][i], height + 1);
}
}
int main() {
scanf("%d", &n);
v.resize(n + 1);
int a, b, cnt = 0, s1 = 0;
for(int i = 0; i < n - 1; i++) {
scanf("%d%d", &a, &b);
v[a].push_back(b);
v[b].push_back(a);
}
for(int i = 1; i <= n; i++) {
if(visit[i] == false) {
dfs(i, 1);
if(i == 1) {
if (temp.size() != 0) s1 = temp[0];
for(int j = 0; j < temp.size(); j++)
s.insert(temp[j]);
}
cnt++;
}
}
if(cnt >= 2) {
printf("Error: %d components", cnt);
} else {
temp.clear();
maxheight = 0;
fill(visit, visit + 10010, false);
dfs(s1, 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;
}