zoukankan      html  css  js  c++  java
  • P4006 小 Y 和二叉树

    P4006 小 Y 和二叉树

    题目链接

    ​ 乱搞.

    ​ 一颗二叉树, 每个节点的度数(d_x <= 3).

    ​ 可以发现, 可以作为开头节点的点一定是度数小于等于2的.

    ​ 然后我们找到编号最小, 度数小于等于2的点(s), 把它作为根, 算出(min[x]).

    (min[x])表示在以(s)为根的二叉树中, 节点(x)的子树内的可以作为这一段开头结点的编号最小的点.

    ​ 对于一个点(x), 它由(fa)走过来, 那么这个点可能为(fa)的右儿子, 也可能为(fa)点的父亲.

    ​ 对于第一种情况, (x)要往下分左,右儿子(如果有两条出边的话), 第二种情况就是一条边通向父亲, 另一条边通向右儿子. 具体看代码吧.

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
    	long long s = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    	return s * f;
    }
    
    const int N = 1e6 + 5;
    int n, s, cnt;
    int d[N], f[N], head[N];
    struct edge { int to, nxt; } e[N << 1];
    
    void add(int x, int y) {
    	e[++ cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; 
    }
    
    void get_tree(int x, int fa) {
    	f[x] = n + 1; int res = 0;
    	for(int i = head[x]; i ; i = e[i].nxt) {
    		int y = e[i].to; if(y == fa) continue ;
    		get_tree(y, x); f[x] = min(f[x], f[y]); res ++;
    	}
    	if(res < 2) f[x] = min(f[x], x);
    }
    
    void make_ans(int x, int fa, int p) { //p = 0代表上面说的情况1, p = 1代表上面说的情况二
    	d[x] --;
    	if(!d[x]) { printf("%d ", x); return ; }
    	if(p) {
    		printf("%d ", x);
    		if(d[x] == 1) {
    			int t;
    			for(int i = head[x]; i ; i = e[i].nxt) {
    				int y = e[i].to; if(y == fa) continue ; t = y;
    			}
    			make_ans(t, x, f[t] == t); //如果说f[t] = t, 说明这个点作为父亲优先输出是更优的
    		}
    		else {
    			int t1, t2;
    			for(int i = head[x]; i ; i=  e[i].nxt) {
    				int y = e[i].to; if(y == fa) continue ; t2 = t1; t1 = y;
    			}
    			if(f[t1] < f[t2]) make_ans(t1, x, 0), make_ans(t2, x, 1);
    			else make_ans(t2, x, 0), make_ans(t1, x, 1);
    		}
    	}
    	else {
    		if(d[x] == 1) {
    			int t;
    			for(int i = head[x]; i ; i = e[i].nxt) {
    				int y = e[i].to; if(y == fa) continue ; t = y;
    			}
    			if(f[t] < x) {
    				make_ans(t, x, 0); printf("%d ", x); //t作为左子树
    			}
    			else {
    				printf("%d ", x); make_ans(t, x, 0); //t作为右子树
    			}
    		}
    		else {
    			int t1, t2;
    			for(int i = head[x]; i ; i=  e[i].nxt) {
    				int y = e[i].to; if(y == fa) continue ; t2 = t1; t1 = y;
    			}
    			if(f[t1] < f[t2]) {
    				make_ans(t1, x, 0);
    				printf("%d ", x);
    				make_ans(t2, x, 0);
    			}	
    			else {
    				make_ans(t2, x, 0);
    				printf("%d ", x);
    				make_ans(t1, x, 0);
    			}
    		}
    	}
    }
    
    int main() {
    
    	n = read(); s = n + 1;
    	for(int i = 1, x;i <= n; i++) {
    		x = read(); d[i] = x;
    		for(int j = 1;j <= x; j++) add(i, read());
    	}
    	for(int i = 1;i <= n; i++) if(d[i] <= 2) { s = i; break; }  //找出可以作为开头结点的编号最小的点
    	get_tree(s, 0); d[s] ++; make_ans(s, 0, 1); //s肯定是情况二, 因为它是左儿子或者根
    
    	return 0;
    }
    
  • 相关阅读:
    【每日日报】第四十六天
    jsp动作标识
    JSP注释
    request对象
    Servlet的创建和配置
    基于图书管理系统的浏览
    在JSP中应用JavaBean
    交流会
    基于图书管理系统的改
    基于图书管理系统的增
  • 原文地址:https://www.cnblogs.com/czhui666/p/14050806.html
Copyright © 2011-2022 走看看