树的深搜和广搜

Posted 1-0001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的深搜和广搜相关的知识,希望对你有一定的参考价值。

树的深搜:

树的重心

技术图片

 

 技术图片

 

 思路:我们可以遍历每一个节点,获取当前节点除外以后的每一个连通块中的点的数量,用一个res变量存储,每次到最后的时候用一个ans存储res中的最小值。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 const int N = 1e5+10;
 8 
 9 int e[2 * N], ne[2 * N], h[N], idx;
10 bool st[N];
11 int n;
12 int ans = N;
13 
14 void add(int a, int b)
15 {
16     e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
17 }
18 
19 int dfs(int u)
20 {
21     st[u] = true;//标记此点已被搜过
22     
23     int sum = 1, res = 0;//sum表示加上当前节点和其子树的节点数个数,因为至少有自己一个节点,所以初始为1
24     for(int i = h[u] ; ~i ; i = ne[i])//遍历子节点
25     {
26         int j = e[i];
27         if(!st[j])//没有访问过
28         {
29             int s = dfs(j);//s表示当前节点所在连通块节点总数
30             res = max(res, s);//与子树节点作比较取最大
31             sum += s;//将子树节点个数加入sum
32         }
33     }
34     res = max(res, n - sum);//与上方的节点取最大值
35     
36     ans = min(ans, res);//按要求求最小的值
37     
38     return sum;//将以此节点为根的树的节点总数返回
39 }
40 
41 int main(){
42     cin >> n;
43     
44     memset(h, -1, sizeof h);
45     
46     for(int i = 0 ; i < n ; i ++)
47     {
48         int a, b;
49         cin >> a >> b;
50         add(a, b), add(b, a);
51     }
52     
53     dfs(1);//随便找一个点开始搜索
54     
55     cout << ans << endl;
56     
57     return 0;
58 }

 

 

树的广搜:

技术图片

 

 运用广搜搜图或者树,就是层次遍历。类似与求解迷宫最短路径,可以先将表示距离的d数组初始化为-1,这样就不需要再开一个st数组记录是否访问过该点,如果该点的dis是-1就说明还未访问过。然后就是普通的广搜。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 const int N = 100010;
10 
11 int n, m;
12 int h[N], e[N], ne[N], idx;
13 int d[N];
14 
15 void add(int a, int b)
16 {
17     e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
18 }
19 
20 int bfs()
21 {
22     memset(d, -1, sizeof d);//初始化
23 
24     queue<int> q;
25     d[1] = 0;
26     q.push(1);
27 
28     while (q.size())
29     {
30         int t = q.front();
31         q.pop();
32 
33         for (int i = h[t]; ~i ; i = ne[i])
34         {
35             int j = e[i];
36             if (d[j] == -1)//如果该节点未访问就访问
37             {
38                 d[j] = d[t] + 1;
39                 q.push(j);//将其加入队列
40             }
41         }
42     }
43 
44     return d[n];
45 }
46 
47 int main()
48 {
49     scanf("%d%d", &n, &m);
50     memset(h, -1, sizeof h);
51 
52     for (int i = 0; i < m; i ++ )
53     {
54         int a, b;
55         scanf("%d%d", &a, &b);
56         add(a, b);
57     }
58 
59     cout << bfs() << endl;
60 
61     return 0;
62 }

以上是关于树的深搜和广搜的主要内容,如果未能解决你的问题,请参考以下文章

深搜和广搜的原理及优缺点

最短路问题------分别用深搜和广搜去解题

利用c++中的栈与树结构,用数组设计二叉树,实现深搜和广搜

广搜和深搜

oj 1792:迷宫 广搜和深搜

算法-图是否为树(并查集或深搜)