• 树的遍历——DFS与BFS


    posted on 2019-08-28 16:45:21

    A.树的遍历

    题目描述

    给定一棵 (n) 个节点的无根树(节点编号 (0)(n-1))和一个节点(x),请以 (x) 号节点为根,做一次 DFS 与一次 BFS

    输入格式

    从标准输入读入数据。

    第一行输入一个正整数 (n)(1 leq n leq 200000)),代表这棵树的节点数目。

    接下来 $ n-1 $ 行(行编号从 $ 1 $ 至 $ n-1 $),第 (i) 行输入一个正整数 $ a_i (() 0 leq a_i leq i $),代表第 (i) 个节点与第 $ a_i $ 个节点之间连有一条边。

    最后一行输入 $ x (() 0 leq x < n $),代表根节点编号。

    输出格式

    输出到标准输出。

    输出 $ 2 $ 行,每行 $ n $ 个数,第 $ 1 $ 行代表 DFS 序,第 $ 2 $ 行代表 BFS 序。

    注意:如果一个节点有多个儿子,那么应按照儿子编号递减的顺序去遍历。

    样例1输入

    7
    0
    1
    0
    0
    1
    4
    1
    

    样例1输出

    1 5 2 0 4 6 3 
    1 5 2 0 4 3 6 
    

    解:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    using namespace std;
    vector<int> to[200005];
    int n,a,vis[200005],q[200005],start;
    int cmp(int b,int c)
    {
    	return b>c;
    }
    void ad(int u,int v)
    {
    	to[u].push_back(v);
    }
    void dfs(int k)
    {
    	cout << k << ' ';
    	for(int i=0;i<to[k].size();i++)
    	{
    		if(vis[to[k][i]]==0)
    		{
    			vis[to[k][i]]=1;
    			dfs(to[k][i]);
    		}
    			
    	}
    }
    void bfs(int k)
    {
    	int head=1,tail=1;
    	q[tail]=k;
    	tail++;
    	while(head<tail)
    	{
    		int now=q[head];
    		cout << now << " ";
    		head++;
    		for(int i=0;i<to[now].size();i++)
    		{
    			if(vis[to[now][i]]==0)
    			{
    				vis[to[now][i]]=1;
    				q[tail]=to[now][i];
    				tail++;
    			}
    		}
    	}
    }
    int main()
    {
    	cin >> n;
    	for(int i=1;i<=n-1;i++)
    	{
    		cin >> a;
    		ad(a,i);
    		ad(i,a);
    	}
    	cin >> start;
    	for(int i=0;i<n;i++)
    		sort(to[i].begin(),to[i].end(),cmp);
    	/*for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<to[i].size();j++)
    		cout << to[i][j] << " ";
    		cout << endl;
    	}*/
       //对于有根树,将start换成根节点即可
    	vis[start]=1;
    	dfs(start);
    	memset(vis,0,sizeof(vis));
    	cout << endl;
    	vis[start]=1;
    	bfs(start);
    return 0;
    }
    
    

    B.树的直径和中心

    题目描述

    给定一棵 (n) 个节点的无根树(节点编号 (0)(n-1)),所有边长均为 (1),求出该树的直径长度。

    定义树的中心为距离树上所有节点距离的最大值最小的节点(一棵树的中心可能不止一个),输出该树的中心。

    输入格式

    从标准输入读入数据。

    第一行输入一个正整数 (n)(1 leq n leq 200000)),代表这棵树的节点数目。

    接下来 (n-1) 行(行编号从 (1)(n-1)),第 (i) 行输入一个正整数 (a_i)(0 leq a_i <i)),代表第 (i) 个节点与第 (a_i) 个节点之间连有一条边。

    输出格式

    输出到标准输出。

    输出 (2) 行,第 (1) 行一个整数,代表树的直径;第 (2) 行按照编号递增顺序输出若干个整数,代表树的中心节点编号。

    样例1输入

    6
    0
    1
    0
    0
    1
    

    样例1输出

    3
    0 1 
    

    解:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    using namespace std;
    vector<int> to[200005];
    int n, a, vis[200005], q[200005], step[200005][2], head = 1, tail = 1, cen[3];
    int cmp(int b, int c) { return b > c; }
    void ad(int u, int v) { to[u].push_back(v); }
    void bfs(int k) {
        head = 1;
        tail = 1;
        q[tail] = k;
        tail++;
        while (head < tail) {
            int now = q[head];
            head++;
            for (int i = 0; i < to[now].size(); i++) {
                if (vis[to[now][i]] == 0) {
                    vis[to[now][i]] = 1;
                    q[tail] = to[now][i];
                    step[tail][0] = step[head - 1][0] + 1;
                    step[tail][1] = head - 1;
                    tail++;
                }
            }
        }
    }
    int main() {
        cin >> n;
        for (int i = 1; i <= n - 1; i++) {
            cin >> a;
            ad(a, i);
            ad(i, a);
        }
        for (int i = 0; i < n; i++) sort(to[i].begin(), to[i].end(), cmp);
        vis[0] = 1;
        bfs(0);
        int point = q[head - 1];
        memset(vis, 0, sizeof(vis));
        memset(step, 0, sizeof(step));
        vis[point] = 1;
        bfs(point);
        int lenth = step[tail - 1][0];
        cout << lenth << endl;
        if (lenth % 2 == 0) {
            for (int i = tail - 1; i > 0; i = step[i][1]) {
                if (step[i][0] == lenth / 2) {
                    cen[1] = q[i];
                    cout << cen[1] << endl;
                    return 0;
                }
            }
        } else {
            for (int i = tail - 1; i > 0; i = step[i][1]) {
                if (step[i][0] == (lenth + 1) / 2) {
                    cen[1] = q[i];
                }
                if (step[i][0] == (lenth - 1) / 2) {
                    cen[2] = q[i];
                    if (cen[2] < cen[1])
                        swap(cen[2], cen[1]);
                    cout << cen[1] << " " << cen[2] << endl;
                    return 0;
                }
            }
        }
    }
    
  • 相关阅读:
    ng-repeat高级用法
    使用 CSS3 实现超炫的 Loading(加载)动画效果
    ADO.NET访问数据库
    连接查询和分组查询
    T-SQL数据查询基础
    使用SQL语句操作数据
    使用表组织数据
    SQL Sever数据库
    使用属性升级Mybank
    C# 语法
  • 原文地址:https://www.cnblogs.com/xuanfly/p/11808544.html
Copyright © 2020-2023  润新知