*[codility]Country network

本文介绍了一种基于深度优先搜索的树遍历算法,通过记录每个节点到根节点的距离及路径,实现对树中所有叶节点的有效遍历。首先进行深度优先搜索确定每个节点与根节点之间的关系,接着按距离排序并计算最优遍历顺序。

https://codility.com/programmers/challenges/fluorum2014

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1273

http://blog.youkuaiyun.com/caopengcs/article/details/36872627

http://www.quora.com/How-do-I-determine-the-order-of-visiting-all-leaves-of-a-rooted-tree-so-that-in-each-step-I-visit-a-leaf-whose-path-from-root-contains-the-most-unvisited-nodes#

思路如曹博所说,先dfs记录离根的距离,来的方向的前驱。然后按距离排序,之后按此排序求有意义的增加距离。

直观感受是,如果两个叶子在一个分叉上,显然深的节点更先被访问,如果不在一个分叉上,那么先算深的也没什么损失。最后,按照这个权值再对叶子排序一次,就是所要的结果。

#include <iostream>
using namespace std;
void dfs(vector<vector<int>> &tree, vector<int> &parent, vector<int> &depth, vector<bool> &visited, int root, int dep) {
    visited[root] = true;
    depth[root] = dep;
    for (int i = 0; i < tree[root].size(); i++) {
        if (visited[tree[root][i]])
            continue;
        parent[tree[root][i]] = root;
        dfs(tree, parent, depth, visited, tree[root][i], dep + 1);
    }
}

vector<int> solution(int K, vector<int> &T) {
    int n = T.size();
    vector<vector<int>> tree(n);
    for (int i = 0; i < n; i++) {
        if (T[i] != i) {
            tree[i].push_back(T[i]);
            tree[T[i]].push_back(i);
        }
    }
    vector<int> parent(n);
    vector<int> depth(n);
    vector<bool> visited(n);
    dfs(tree, parent, depth, visited, K, 0);
    vector<vector<int>> cnt(n);
    for (int i = 0; i < n; i++) {
        cnt[depth[i]].push_back(i);    
    }
    vector<int> ordered;
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j < cnt[i].size(); j++) {
            ordered.push_back(cnt[i][j]);    
        }
    }
    vector<int> res;
    vector<int> length(n);
    visited.clear();
    visited.resize(n);
    visited[K] = true;
    for (int i = 0; i < ordered.size(); i++) {
        int len = 0;
        int x = ordered[i];
        while (!visited[x]) {
            visited[x] = true;
            x = parent[x];
            len++;
        }
        length[ordered[i]] = len;
        //cout << "length[" << ordered[i] << "]:" << len << endl;
    }
    
    cnt.clear();
    cnt.resize(n);
    for (int i = 0; i < length.size(); i++) {
        cnt[length[i]].push_back(i);    
    }
    res.push_back(K);
    for (int i = cnt.size() - 1; i > 0; i--) {
        for (int j = 0; j < cnt[i].size(); j++) {
            res.push_back(cnt[i][j]);
        }
    }
    return res;
}

  

转载于:https://www.cnblogs.com/lautsie/p/4100869.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值