您的位置:首页 > 其它

loj#2324. 「清华集训 2017」小 Y 和二叉树(贪心+分类讨论)

2018-03-06 00:39 381 查看
题面在这里

题意:

给出一棵每个点度数不超过3的无根树,节点编号为11~nn

你需要确定根和每个节点的左右儿子,使其成为一棵二叉树。

问所有可得到的二叉树中中序遍历字典序最小的树的中序遍历。

n≤1,000,000n≤1,000,000

做法:

这题似乎当时集训队全场ac

首先找出一个最小的度≤2≤2的点作为最左边的拐角点,也就是中序遍历的第一个数。

然后把这个点当做根,f[u]f[u]表示以uu为根的子树中中序遍历开头的最小值。

每次确定一下这个点uu连向的点当做uu的父亲还是儿子,根据f[u]f[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
, d
, ans
, f
;
struct edge {
int to, nxt;
edge() {}
edge(int x, int y) { to = x; nxt = y; }
} e
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: