UVA #10410 Реконструкция дерева
Я работал над восстановлением дерева UVA 10410 несколько дней. Но сейчас я не могу получить правильный ответ.
Я использовал алгоритм, аналогичный тому, который мы всегда используем для восстановления бинарного дерева через обход по предзаказу и прохождение по порядку. Но это не может работать.
Может кто-нибудь мне помочь? Заранее спасибо.
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;
}
Я думаю, что у меня есть навык. Я не делаю вид, что это эффективно, хотя.
Давайте посмотрим на первые 3 цифры вывода BFS:
4 3 5
Мы находимся в одной из следующих ситуаций:
4 4
/ \ OR |
3 5 3
x x |
5
x
Что такое DFS для этих двух случаев?
- 4 3 (3-х детей) 5 (5-х детей)
- 4 3 5 (5 детей)
Быстрое примечание: если 3
не имеет ни одного ребенка, тогда невозможно отличить двоих...
Если мы считаем, что проблема разрешима, то это вопрос 5
следует 3
в представлении DFS.
- Если это так: это линейная композиция
- Если это не так, вы идете рекурсивно:
4
имеет 2 детей3
а также5
и вы можете легко идентифицировать поддерево из представления DFS. Затем извлеките (сохраняя порядок) представление BFS этих поддеревьев из имеющейся у вас BFS и рекурсивно:)
Это кажется довольно далеко от оптимального, но я немного больше беспокоюсь о неразрешимости.
Есть ли в деревьях синтаксического анализа ограничение, которое гласит, что если у вас есть узел, у которого есть только один дочерний элемент, ни один из узлов в поддереве, которое он представляет, не может иметь более одного?