目录
一、dfs是什么?
dfs(Depth First Search)叫做深度优先搜索,又叫深度优先遍历
二、代码模板
代码如下:
void dfs(int u) {
st[u] = true;
for(int i = h[u]; i != -1; i = ne[i]) {
int j = ne[i];
if(st[j]) continue;
dfs(j) ... ;
}
}
三、例题引入
给定一颗树,树中包含 n个结点(编号 1∼n)和 n−1条无向边。请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入格式
第一行包含整数 n,表示树的结点数。
接下来 n−1行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出格式
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
数据范围
1≤n≤1e5
输入样例
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出样例
4
思路:
01-利用链式前向星存储题目数据
02-利用dfs模板进行遍历
03-因为会遍历每个点,故时间复杂度为O(n)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 2 * N;
int h[N], e[M], ne[M], idx, n, ans = N;
bool st[N];
void add(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
int dfs(int u) {
st[u] = true;
int sum = 0, size = 0; // sum 记录以u为根的树中的子树结点个数,size保存这些字数的结点个数最大值
for(int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if(st[j]) continue;
int s = dfs(j);
size = max(size, s);
sum += s;
}
size = max(size, n - sum - 1);
ans = min(ans, size); // ans记录最大的最小值
return sum + 1;
}
int main() {
memset(h, -1, sizeof h);
cin >> n;
for(int i = 0; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
dfs(1);
cout << ans << endl;
return 0;
}