绪论
有个问题:什么时候需要记录该点是否已经遍历过?
1.先说结论: D F S DFS DFS不需要记录该点是否已经遍历过
但是你需要知道的是,
如果我们遇到了无向图,那我们需要在dfs()函数中,额外开辟一个参数,用来记录他的父节点,我们需要判断当前节点!=他的父节点,防止他返回去重复遍历
2.先说结论: B F S BFS BFS需要记录该点是否已经遍历过的情况有以下几种:
1)有环
2)无向图
满足以上两个中的任意一个,都需要标记是否该点已经遍历过,否则就会死循环
其他情况的 B F S BFS BFS就不需要标记是否该点已经遍历过
下面来上一道题
Acwing 1207. 大臣的旅费-第四届蓝桥杯省赛C++ A组,第四届蓝桥杯省赛JAVA A组
本题其实就是要找这棵树的直径,下面是求直径的方法
/*
要找到一棵树的直径,可以使用以下步骤:
选择树上任意一个节点作为起点,做深度优先搜索或广度优先搜索,确定离该节点最远的节点。
将上一步中找到的节点作为新的起点,再进行一次深度优先搜索或广度优先搜索,确定离该节点最远的节点。
最终得到的距离就是树的直径。
例如,下面是一棵树:
复制代码
A
/ | \
B C D
/ \ / \
E F G H
以节点A为起点,进行深度优先搜索,可以发现最远的节点是H。
以H为起点,进行深度优先搜索,可以发现最远的节点是E。
因此,树的直径为H到E的距离,即5。
*/
下面提供三种解题的方法
一.用vector存储图 + dfs
//用vector存储图 + dfs
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct Edge
{
int id, w;
};
vector<Edge> h[N];
int dist[N];
//三个参数:当前节点,从哪个节点过来的,从起点到u的权值
void dfs(int u, int father, int distance)
{
dist[u] = distance;
for (auto node : h[u])
if (node.id != father)
dfs(node.id, u, distance + node.w);
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n - 1; i ++ )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
h[a].push_back({
b, c});
h[b].push_back({
a, c});
}
dfs(1, -1, 0);//因为是无向图,放在他往回走,第二个参数存的是他上一个点(他是从哪个点过来的),第三个参数是节点1到当前节点的权值
//因为节点1是根节点,根节点没有父节点,我们就用-1来表示
int u = 1;
for (int i = 1; i <= n; i ++ ){
//cout<<dist[i]<<' ';//可以发现dist[i]存的是从节点1到节点i的权值
if (dist[i] > dist[u])
u = i;
}
//cout<<endl;
dfs(u, -1, 0);
for (int i = 1