zoukankan      html  css  js  c++  java
  • NOI2020 超现实树

    NOI2020 超现实树 surreal

    目标:判定树集 (mathscr{T}) 是否 "几乎完备" 。

    其中,(mathscr{T}) "几乎完备" 当且仅当仅有有限棵树不能被树集 (mathscr{T}) 生成。

    生成定义为:将一个儿子替换为一棵树。

    (sum nle 2 imes 10^6),多次查询。

    Solution

    定义 ( extrm{grow}(mathscr{T})) 表示树集 (mathscr{T}) 的生长集合。

    首先可以发现只有那种 "链树" 是有效的(即不存在一个点同时拥有两个儿子满足他们两个子树大小都大于 (1))。

    假设一棵树 (T) 不为链树,那么不难发现无论多少棵非链树,都无法达到一棵链树可以替换得到的效果。

    所以我们保留所有的链树。

    问题等价于尝试去生成所有的链树。

    (solve(mathscr{T})) 表示树集 ({mathscr{T}}) 能否生成。

    可以发现 (mathscr{T}) 能够生成,当且仅当 (mathscr{F_l+varnothing},mathscr{F_r+varnothing},mathscr{F_l+rs},mathscr{F_r+ls}) 均能够生成。

    那么将树进行分类并递归即可。

    注意到每棵树只能递归 (dep) 次,所以总体复杂度是 (mathcal O(sum dep)),即 (mathcal O(sum n))

    代码非常好写。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    #define vi vector<int> 
    #define pb push_back
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int N = 2e6 + 5 ; 
    int n, m ; 
    vi L[N], R[N], sz[N], Nw, Id ; 
    bool check(vi S, vi nw) {
    	if( S.empty() ) return 0 ; 
    	vi Lv, Rv, Ls, Rs ;
    	vi lv, rv, ls, rs ; int flag = 0 ; 
    	for(re int i = 0; i < S.size(); ++ i) {
    		int x = S[i], u = nw[i] ; 
    		int l = L[x][u], r = R[x][u] ;
    		if( !l && !r ) flag = 1 ; 
    		if( l && sz[x][r] == 0 ) Lv.pb(x), lv.pb(l) ; 
    		if( r && sz[x][l] == 0 ) Rv.pb(x), rv.pb(r) ; 
    		if( l && sz[x][r] == 1 ) Ls.pb(x), ls.pb(l) ;
    		if( r && sz[x][l] == 1 ) Rs.pb(x), rs.pb(r) ;
    	}
    	if( flag ) return 1 ; 
    	flag = 1 ; 
    	flag &= check(Lv, lv),
    	flag &= check(Ls, ls),
    	flag &= check(Rv, rv),
    	flag &= check(Rs, rs) ;
    	return flag ; 
    }
    void Dfs(int id, int x) {
    	sz[id][x] = 1 ; int l = L[id][x], r = R[id][x] ; 
    	if(l) Dfs(id, l), sz[id][x] += sz[id][l] ; 
    	if(r) Dfs(id, r), sz[id][x] += sz[id][r] ; 
    }
    signed main()
    {
    	int T = gi() ; 
    	while( T-- ) {
    		m = gi() ; Id.clear() ; 
    		rep( i, 1, m ) {
    			n = gi() ; int l, r ; L[i].pb(0), R[i].pb(0), sz[i].pb(0) ;  
    			rep( j, 1, n ) l = gi(), r = gi(), L[i].pb(l), R[i].pb(r), sz[i].pb(0) ; 
    			Id.pb(i), Dfs(i, 1), Nw.pb(1) ; 
    		}
    		if( check(Id, Nw) ) puts("Almost Complete") ;
    		else puts("No") ;
    		rep( i, 1, m ) L[i].clear(), R[i].clear(), sz[i].clear() ;
    		Id.clear(), Nw.clear() ; 
    	}
    	return 0 ;
    } 
    
  • 相关阅读:
    Java如何编写自动售票机程序
    install windows service
    redis SERVER INSTALL WINDOWS SERVICE
    上传文件
    This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
    解决Uploadify上传控件加载导致的GET 404 Not Found问题
    OracleServiceORCL服务不见了怎么办
    Access to the temp directory is denied. Identity 'NT AUTHORITYNETWORK SERVICE' under which XmlSerializer is running does not have sufficient permiss
    MSSQL Server 2008 数据库安装失败
    数据库数据导出成XML文件
  • 原文地址:https://www.cnblogs.com/Soulist/p/13720295.html
Copyright © 2011-2022 走看看