1.题目
2.求解
看到题目第一眼,想到两种求解可能 1.树形dp 2.并查集
树形dp是我学过的dp里面学的最烂的 所以我想着有没有暴力或者贪心的算法求解,怎奈我脑子没那么灵光。最后是参考了三叶姐(Leetcode的一位大牛)的dp写法。
其实这道题没有很难,是树形dp题的简单拓展,增加了对父节点的判断,两个dfs都是基础模板里也需要的。(说的很简单,其实我写的时候完全忘了 我可太菜了)
这题就是默认从0节点起步,每次判断子节点中最深的那条的深度和父节点的深度进行比较取较大的那条。最后对所有的节点进行遍历找到深度最小的节点。需要注意的是,求解子节点深度的时候不仅要保存最深的深度,也要保存次深的那条,因为和父节点的最深的那条路径比较的时候,可能就是当前路径,也就是父节点指向的也是当前节点,因此需要多保存一条路径数据。(如果看不懂我在说什么,请去看一看树形dp模板,基础很重要!!!)
慢慢加油 一点一点把以前学过的东西捡起来加油加油!!
3.代码
这次放的是我自己在visual studio上写的可以直接测试的代码,如果放leetcode上需要自己修改一部分。
顺带一题我写的时候发现我想创建next数组却不行有红线(next不明确),如果有知道是为什么的大佬请告知一下,万分感谢!
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2 * 10000 + 100;
int index = 0;
int deep[maxn];
int secdeep[maxn];
int up[maxn];
int down[maxn];
int head[maxn];
int to[maxn * 2];
int ne[maxn];
void addl(int x, int y) {
to[index] = y;
ne[index] = head[x];
head[x] = index;
index++;
}
int dfsdown(int pos, int fa) {
for (int i = head[pos]; i != -1; i = ne[i]) {
int j = to[i];
// cout<<j<<" ";
if (j == fa) continue;
int sub = dfsdown(j, pos) + 1;
if (sub > deep[pos]) {
secdeep[pos] = deep[pos];
deep[pos] = sub;
down[pos] = j;
}
else if (sub > secdeep[pos]) {
secdeep[pos] = sub;
}
}
return deep[pos];
}
void dfsup(int pos, int fa) {
for (int i = head[pos]; i != -1; i = ne[i]) {
int j = to[i];
if (j == fa) continue;
if (down[pos] != j) up[j] = max(deep[pos] + 1, up[j]);
else up[j] = max(secdeep[pos] + 1, up[j]);
up[j] = max(up[j], up[pos] + 1);
dfsup(j, pos);
}
}
int main() {
memset(head, -1, sizeof(head));
memset(ne, -1, sizeof(ne));
int n, m;
cin >> n >> m;
int i, j;
int x, y;
for (i = 0; i < m; i++) {
cin >> x >> y;
addl(x, y);
addl(y, x);
}
dfsdown(0, -1);
dfsup(0, -1);
queue<int> q;
int min = n;
for (int i = 0; i < n; i++) {
int cur = max(deep[i], up[i]);
//cout << i << " " << cur << endl;
if (cur < min) {
min = cur;
while (!q.empty()) q.pop();
q.push(i);
}
else if (cur == min) {
q.push(i);
}
}
while (!q.empty()) {
cout << q.front() << " ";
q.pop();
}
return 0;
}
/*
4 3
1 0
1 2
1 3
*/