题意:
给出一棵每个点度数不超过3的无根树,节点编号为
1
1
~
你需要确定根和每个节点的左右儿子,使其成为一棵二叉树。
问所有可得到的二叉树中中序遍历字典序最小的树的中序遍历。
n≤1,000,000
n
≤
1
,
000
,
000
做法:
这题似乎当时集训队全场ac
首先找出一个最小的度
≤2
≤
2
的点作为最左边的拐角点,也就是中序遍历的第一个数。
然后把这个点当做根,
f[u]
f
[
u
]
表示以
u
u
为根的子树中中序遍历开头的最小值。
每次确定一下这个点连向的点当做
u
u
的父亲还是儿子,根据来分类讨论。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
inline ll read() {
char ch = getchar(); ll x = 0; int op = 1;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;
for(; isdigit(ch); ch = getchar()) x = (x<<1)+(x<<3)+ch-'0';
return x*op;
}
const int N = 2000010;
int n, cnt, flag, chk, tot, rt;
int head[N], d[N], ans[N], f[N];
struct edge {
int to, nxt;
edge() {}
edge(int x, int y) { to = x; nxt = y; }
} e[N];
inline void addedge(int x, int y) { e[++ cnt] = edge(y, head[x]); head[x] = cnt; }
inline void dfs(int u, int lst) {
for(int i = head[u], v; i; i = e[i].nxt) if((v = e[i].to) != lst) {
dfs(v, u); f[u] = min(f[u], f[v]);//f[u]表示以u为根的子树中中序遍历开头的最小值
}
}
inline void get(int u, int lst) {
for(int i = head[u], v; i; i = e[i].nxt) if((v = e[i].to) != lst && f[v] == f[u]) get(v, u);
ans[++ tot] = u;
for(int i = head[u], v; i; i = e[i].nxt) if((v = e[i].to) != lst && f[v] != f[u]) get(v, u);
}
int main() {
/*freopen("binary.in", "r", stdin);
freopen("binary.out", "w", stdout);*/
n = read();
for(int i = 1; i <= n; i ++) {
d[i] = read();
for(int j = 1; j <= d[i]; j ++) {
int x = read(); addedge(x, i);
}
}
for(int i = 1; i <= n; i ++)
if(d[i] <= 2) { rt = i; break; }
for(int i = 1; i <= n; i ++) if(d[i] <= 2) f[i] = i; else f[i] = n+1;
dfs(rt, 0);// for(int i = 1; i <= n; i ++) printf("%d ", f[i]); puts("");
for(int u = rt, lst = 0; ; ) {
ans[++ tot] = u; int c[5], ch = 0;
for(int i = head[u], v; i; i = e[i].nxt) if((v = e[i].to) != lst) c[++ ch] = v;
if(!ch) break;
if(ch == 1) {
if(f[c[1]] < c[1]) { get(c[1], u); break; }
else { lst = u; u = c[1]; }
}
if(ch == 2) {
if(f[c[1]] > f[c[2]]) swap(c[1], c[2]);
get(c[1], u); lst = u; u = c[2];
}
}
for(int i = 1; i <= n; i ++) printf("%d ", ans[i]);
return 0;
}