loj#2324. 「清华集训 2017」小 Y 和二叉树(贪心+分类讨论)
2018-03-06 00:39
381 查看
题面在这里
你需要确定根和每个节点的左右儿子,使其成为一棵二叉树。
问所有可得到的二叉树中中序遍历字典序最小的树的中序遍历。
n≤1,000,000n≤1,000,000
首先找出一个最小的度≤2≤2的点作为最左边的拐角点,也就是中序遍历的第一个数。
然后把这个点当做根,f[u]f[u]表示以uu为根的子树中中序遍历开头的最小值。
每次确定一下这个点uu连向的点当做uu的父亲还是儿子,根据f[u]f[u]来分类讨论。
题意:
给出一棵每个点度数不超过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; }
相关文章推荐
- 【JZOJ5295】【清华集训2017模拟】Create
- 2017沈阳网络赛G XOR 分块(分类讨论sqrt)
- jzoj5317 【清华集训2017模拟8.19】func (寻找性质)
- 「清华集训 2017」小Y和地铁
- [jzoj]5483. 【清华集训2017模拟11.26】简单路径
- [LOJ2325][清华集训 2017]小Y和恐怖的奴隶主 矩阵乘法+奇技淫巧
- JZOJ 5496. 【清华集训2017模拟12.09】Tree
- 【清华集训2017模拟12.09】塔
- 【JZOJ 5276】【清华集训2017模拟】神奇的玩具
- 【JZOJ 5284】【清华集训2017模拟】超级翻转
- 【JZOJ5296】【清华集训2017模拟】Sequence
- JZOJ 5484. 【清华集训2017模拟11.26】快乐树
- JZOJ5484. 【清华集训2017模拟11.26】快乐树
- JZOJ5489. 【清华集训2017模拟11.28】海明距离
- [JZOJ5495]【清华集训2017模拟12.09】MiniumCut
- LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)
- [JZOJ5500]【清华集训2017模拟12.10】营养餐
- JZOJ5498. 【清华集训2017模拟12.10】大佬的难题
- 【分类讨论】【计算几何】【凸包】hihocoder 1582 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 E. Territorial Dispute
- 【清华集训 2017】小Y的地铁 [模拟退火]