UVA#10410树木重建

时间:2010-04-21 07:51:40

标签: algorithm tree onlinejudge

我已经在UVA 10410 Tree Reconstruction工作了几天。但我现在无法得到正确答案。

我使用的算法类似于我们用来通过前序遍历和顺序遍历来恢复二叉树的算法。但它不起作用。

任何人都可以帮助我吗?提前谢谢。

2 个答案:

答案 0 :(得分:0)

我想我已经掌握了它。我不会假装它有效率。

让我们看一下BFS输出的前3位数字:

4 3 5

我们处于以下某种情况:

  4         4
/  \   OR   |
3  5        3
x  x        |
            5
            x

这两种情况的DFS是什么?

  • 4 3(3s-children)5(5s-children)
  • 4 3 5(5s-children)

快速说明:如果3没有任何孩子,那么就不可能将两者分开......

如果我们认为问题是可判定的,则需要知道DFS表示中5后面是否3

  • 如果确实如此:它是线性构图
  • 如果没有,则递归:4有2个孩子35,您可以轻松地从DFS表示中识别子树。然后从你拥有的BFS中提取(保留顺序)这些子树的BFS表示并递归:)

这似乎距离最优,但我更担心不确定性。

表达式解析树中是否存在一个约束,它表明一旦你有一个只有一个子节点的节点,它所代表的子树中没有一个节点可以有多个节点?

答案 1 :(得分:-2)

  

“请注意,当父母被扩展时,孩子们被遍历了   升序。“   这句话非常重要!

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Node
{
    int value;
    Node *child; //left child
    Node *sibling; //right sibling

    Node(int v)
    {
        value = v;
        child = NULL;
        sibling = NULL;
    }
};

void BuildTree(Node *&root,vector<int> bfs,vector<int> dfs)
{
    root = NULL;
    if(bfs.size() == 1)
        root = new Node(bfs[0]);
    if(bfs.size() > 1)
    {
        root = new Node(bfs[0]);

        vector<int> candidate; //store candidate childs
        unsigned i;
        for(i = 1; i < bfs.size(); i++)
        {
            if(bfs[i] >= bfs[1])
                candidate.push_back(bfs[i]);
            else
                break;
        }

        //remove the non-candidate node
        int boundOfChild = candidate.size() - 1;
        for(i = candidate.size() - 1; i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            it1 = find(dfs.begin(),dfs.end(),candidate[i]);
            it2 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
            if(it1 < it2)
                boundOfChild = i;
        }
        if(boundOfChild != candidate.size() - 1)
            candidate.erase(candidate.begin() + boundOfChild,candidate.end());

        //get every child's bfs and dfs
        for(i = candidate.size(); i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            if(i == candidate.size())
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = dfs.end();
            }
            else
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = find(dfs.begin(),dfs.end(),candidate[i]);
            }

            vector<int> tmp_dfs(it1,it2);
            vector<int> tmp_bfs;
            for(vector<int>::iterator it = bfs.begin(); it < bfs.end(); it++)
            {
                if(find(tmp_dfs.begin(),tmp_dfs.end(),*it) != tmp_dfs.end())
                    tmp_bfs.push_back(*it);
            }

            Node *tmp = root->child;
            BuildTree(root->child,tmp_bfs,tmp_dfs);
            root->child->sibling = tmp;
        }
    }
}

void PrintTree(Node *root)
{
    if(root == NULL)
        return;
    queue<Node*> Q;
    Q.push(root);
    while(!Q.empty())
    {
        Node *tmp = Q.front();
        Q.pop();
        cout << tmp->value << ": ";
        tmp = tmp->child;
        while(tmp)
        {
            cout << tmp->value << ",";
            Q.push(tmp);
            tmp = tmp->sibling;
        }
        cout << endl;
    }
}

//just test case
int BFS[] = {7,8,12,4,5,1,6,11,2,3,10,9,13,14};
int DFS[] = {7,8,4,5,2,3,12,1,6,10,14,11,9,13};

int main()
{
    vector<int> vBFS(BFS,BFS + sizeof(BFS) / sizeof(int));
    vector<int> vDFS(DFS,DFS + sizeof(DFS) / sizeof(int));

    Node *root = NULL;
    BuildTree(root,vBFS,vDFS);    
    PrintTree(root);

    return 0;
}