无根树转有根树

无根树的定义:离散数学中,无根树指无环连通无向图。由于树是图的子集,这一类图具有树的特征,但不具有树状的形式,没有特定的根节点,故称为无根树。任意选取图中某个点为根,均可将无根树转化成为有根树。

有n个顶点的树具有以下3个特点:连通、不含圈、恰好包含n-1条边。具备上述3个特点中的任意两个,就可以推导出第3个。

树是边数最多的无回路图,树是边数最少的连通图。

用vector数组表示。由于n个结点的树只有n-1条边,vector数组实际占用的空间与n成正比。
 1 const int maxn = 100010;
 2 vector<int>    G[maxn];
 3 void read_tree() {
 4     int u, v;
 5     scanf("%d", &n);
 6     for(int i = 0; i < n - 1; i++){
 7         scanf("%d%d", &u, &v);
 8         G[u].push_back(v);
 9         G[v].push_back(u);
10     }
11 }

转化过程如下:

1 int p[maxn];
2 void dfs(int u, int fa) {
3     int d = G[u].size();
4     for(int i = 0; i < d; i++) {
5         int v = G[u][v];
6         if(v != fa)
7             dfs(v, p[v] = u);
8     }
9 }

主程序中设置p[root] = -1(表示根节点的父节点不存在),然后调用dfs(root, -1)即可。这里容易忘记判断v是否和其父节点相等。如果忽略,将引起无限递归。

例题(南洋理工OJ20 吝啬的国度)

链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=20

吝啬的国度

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
 
描述
在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来。现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路)。
输入
第一行输入一个整数M表示测试数据共有M(1<=M<=5)组
每组测试数据的第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000),N表示城市的总个数,S表示参观者所在城市的编号
随后的N-1行,每行有两个正整数a,b(1<=a,b<=N),表示第a号城市和第b号城市之间有一条路连通。
输出
每组测试数据输N个正整数,其中,第i个数表示从S走到i号城市,必须要经过的上一个城市的编号。(其中i=S时,请输出-1)
样例输入
1
10 1
1 9
1 8
8 10
10 3
8 6
1 2
10 4
9 5
3 7
样例输出
-1 1 10 10 9 8 3 1 1 8
AC代码如下:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 using namespace std;
 5 const int maxn = 100010;
 6 vector<int> G[maxn];
 7 int N, S; 
 8 void read_tree(){
 9     int u, v;
10     for(int i = 1; i < N; i++){//注意要清理数据; 
11         G[i].clear();
12     }
13     for(int i = 1; i < N; i++){
14         scanf("%d%d", &u, &v);
15         G[u].push_back(v);
16         G[v].push_back(u);
17     }
18 }
19 int p[maxn];
20 void dfs(int u, int fa){
21     int d = G[u].size();
22     for(int i = 0; i < d; i++){
23         int v = G[u][i];
24         if(v != fa)
25             dfs(v, p[v] = u);
26     }
27 }
28 int main(){
29     int M;
30     cin >> M;
31     while(M--){
32         cin >> N >> S;
33         read_tree();
34         p[S] = -1;
35         dfs(S, -1);
36         for(int i = 1; i <= N; i++){
37             printf("%d ", p[i]);
38         }
39         cout << endl;
40     }
41     return 0;
42 }

第一次由于没有清理vector中的数据,造成RE。须汲取教训!

 
 
原文地址:https://www.cnblogs.com/lulizhiTopCoder/p/8934507.html