题目大意
以括号包含的方式,给你一棵树,然后每次去掉编号最小的叶子节点并输出它的父节点。
题解
算是一道STL题目吧
首先需要把一棵树处理,存储起来,我们用set建立相邻节点集合,也就是某个节点的set里面包含了所有和这个节点相邻的其他节点,然后我们建一个set数组,就是每个节点的set,当然也可以vector< set<int> >
。
建图的话,可以递归,对于某个节点(数字),它的下一个字符,要么是"(“要么是”)",如果是左括号,我们就递归处理,右括号则返回
然后去点这个操作其实类似拓扑排序啊(当然是不一样的)
我们把每个叶子节点取出来,放到一个小根堆里面,然后每次取出最小的,输出和他相邻的节点ID,并把他从和他相邻的节点中去掉,再判断下相邻节点是不是变成了叶子节点,如果是就入堆。
code
一星期没打代码,做完60页长的PPT作业,发现代码又打不来了……
#include <iostream>
#include <set>
#include <vector>
#include <queue>
using namespace std;
void build_ (vector <set<int> > & vec, int p = 0) {
int x;
cin >> ws >> x;
if (p) {
vec[p].insert (x);
vec[x].insert (p);
}
while (true) {
char c;
cin >> ws >> c;
if (c == ')') break;
build_ (vec, x);
}
}
int main () {
char c;
while (cin >> ws >> c) {
vector <set <int> > v (1024, set<int> ());
build_ (v);
priority_queue <int, vector <int>, greater <int> > que;
int n = 0;
for (int i = 0;i < v.size (); ++ i) {
if (v[i].size ()) {
++ n;
if (v[i].size () == 1) {
que.push (i);
}
}
}
for (int k = 1; k < n; ++ k) {
int now = que.top (); que.pop ();
int pa = *(v[now].begin ()); /// now 为叶子节点
v[pa].erase (now);
if (k > 1) cout << ' ';
cout << pa;
if (v[pa].size () == 1) {
que.push (pa);
}
}
cout << endl;
}
return 0;
}