算法竞赛入门经典第11章 无根树转有根树

题目:输入一个n个结点的无根树的各条边,并指定一个根节点,要求把该树转化为有根树,输出各个节点的父亲编号, n ≤ 1 0 6 n\leq10 ^6 n106

可以把无根树看作无向无环且连通的稀疏图,所要做的就是从指定节点开始,深度搜索遍历所有节点,每次遍历等同于从根节点到叶子节点的过程,遍历过程中经过的节点按照先后保存为父亲节点和子节点。

首先读入数据,数据按照每条边的起点和终点输入,可以用邻接表保存,也可以用类似邻接表的二维数组保存,第i行代表以i为起点的边;第i行每个值v代表存在边(u, v)。树的结点数为n时边数为n-1。因为是无向图,每条边只输入一次,但要按照起点-终点,终点-起点保存两次。
算法竞赛入门经典第11章 无根树转有根树_第1张图片
测试数据(0, 1), (0, 2), (0, 3), (1, 4), (1, 5), (5, 6), (5, 7)

int n;
vector<vector<int>> tree(1000001); 
void read()
{
    int a, b, i = 0;
    cout<<"Input number of vertices: ";
    cin>>n;
    while(i++ < n-1 && cin >> a && cin >> b) //分别输入n-1条边的起点和终点
    {
        tree[a]. push_back(b);
        tree[b]. push_back(a);
    }
    tree.shrink_to_fit(); //去掉不必要空间
}

接下来使用深度搜索遍历树,从根结点开始,找到每个与它相邻的点,找到以后将这个相邻点的父亲设为根节点,再用相同的方法将每个相邻结点作为根节点继续遍历。由于每条边存在两次(u-v, v-u),可能已经设定u的父亲节点是v,当对v搜索时,搜索到相邻点u不能再将u的父亲设为v,否则会引起无限递归。因此需要判断if(v != u的父亲节点)。

int n;
vector<vector<int>> tree(1000001);
vector<int> p(1000001, -1);

void dfs(int current) //current为当前根节点
{
   for(int i = 0; i < tree[current].size(); i++)
   {
        if(tree[current][i] != p[current])
        {
            p[tree[current][i]] = current;
            dfs(tree[current][i]);
        }
   }
   p.shrink_to_fit();
}

完整代码及主函数:

#include
#include
using namespace std;

int n;
vector<vector<int>> tree(1000001);
vector<int> p(1000001, -1);

void read()
{
    int a, b, i = 0;
    cout<<"Input number of vertices: ";
    cin>>n;
    while(i++ < n-1 && cin >> a && cin >> b)
    {
        tree[a]. push_back(b);
        tree[b]. push_back(a);
    }
    tree.shrink_to_fit();
}

void dfs(int current)
{
   for(int i = 0; i < tree[current].size(); i++)
   {
        if(tree[current][i] != p[current])
        {
            p[tree[current][i]] = current;
            dfs(tree[current][i]);
        }
   }
   p.shrink_to_fit();
}

int main()
{
    read();
    int root;
    cout<<"Input root number: ";
    cin>>root;
    dfs(root);
    for(int i = 0; i < n; i++)
    {
        if(p[i] == -1) cout << "Root is " << i << endl;
        else cout << "the parent of " << i << " is " << p[i] << endl;
    }

}

结果:
算法竞赛入门经典第11章 无根树转有根树_第2张图片

你可能感兴趣的:(算法竞赛入门经典)