• 无根树转有根树


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

    有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。须汲取教训!

     
     
  • 相关阅读:
    很多人知道外包的种种不好,但还是选择去外包,这是为什么呢?
    微信聊天内容可以被监听吗
    Go 语言笔试面试题(实现原理)
    oracle中正则表达式相关函数regexp_like简介
    These 30 keyboard shortcuts are guaranteed to save you time in After Effects.
    Why is git submodule not updated automatically on git checkout?
    WPF DataBinding: Nullable Int still gets a validation error?
    How to make a dropdown list of all cultures (but no repeats)
    米象
    How To Bind a Combobox to a Dictionary in WPF C#
  • 原文地址:https://www.cnblogs.com/lulizhiTopCoder/p/8934507.html
Copyright © 2020-2023  润新知