zoukankan      html  css  js  c++  java
  • [loj3343]超现实树

    定义1:两棵树中的$x$和$y$对应当且仅当$x$到根的链与$y$到根的链同构
    定义2:$x$和$y$的儿子状态相同当且仅当$x$与儿子所构成的树与$y$与儿子所构成的树同构
    根据题中所给的定义,有以下两个的结论(观察可得,证明略):
    结论1:对于两棵树$T_{1}$和$T_{2}$,$T_{1}->T_{2}$当且仅当对于$T_{1}$中的非叶子节点$x$和$T_{2}$中对应的点$y$,$x$和$y$的儿子状态相同
    结论2:$grow(mathscr{T})$几乎完备当且仅当不存在一棵树$T'$使得$max h<h(T')$且$forall 1le ile n,T_{i} e >T'$
    这两个结论都比较显然,考虑继续发掘一些更有用的结论——
    定义3:$T$为“链树”当且仅当其存在一条由根到某个叶子的链,使得树上任意一点到链上最近的点距离不超过1
    结论3:对于树$T_{1}$和链树$T_{2}$,$T_{1}->T_{2}$当且仅当$T_{1}$为链树且$T_{2}$中所有深度不超过$h(T_{1})$的点所组成的树与$T_{1}$同构
    (这个就是结论1通过观察得到的推论,即要求$T_{1}$是$T_{2}$的一个“前缀”(不太严谨),证明略)
    结论4:$grow(mathscr{T})$几乎完备当且仅当不存在一棵“链树”$T'$使得$max h<h(T')$且$forall 1le ile n,T_{i} e >T'$
    证明:观察到仅将树改为了“链树”,由于“链树”的必要条件是树,结论2即必要性
    考虑充分性,构造:对于一棵符合条件的树$T'$,将$T'$中最深的点(多个任选一个)到根的链作为$T''$的那条链,保留$T''$中所有到这条链距离为1的点(删去其他点),所构成的树显然为“链树”,接下去证明其符合条件
    由于最长的链被保留,因此$max h<h(T')=h(T'')$
    由于$forall 1le ile n,T_{i} e >T'$,必然有非叶子节点$x$使得$x$和$T'$中对应的点$y$儿子状态不同,令$a_{i}=y$
    1.若$a_{i}$在链上(指“链树”的链),未改变$a_{i}$的儿子状态,仍然符合条件;
    2.若$a_{i}$到链上最近的点距离为1,其儿子一定不被保留,则其为叶子节点而$x$为非叶子节点,儿子状态不同;
    3.若$a_{i}$不被保留,取$a_{i}$为最近的被保留的祖先$z$,不妨设$a_{i}$在$z$的左子树中,由于$T_{i}$中存在$x$因此$z$在$T_{i}$中对应的点有左子树,而现在$z$的左子树必然为空(否则$z$应该取左儿子),即儿子状态不同
    根据这两个结论,可以删去所有不为“链树”的树,然后暴力枚举链树:分为4类,链在(左/右)子树,有无(右/左)儿子,并递归链所在的子树
    枚举时,维护一个$vector$表示当前仍然合法(即设枚举到的链树为$T'$,$T_{i}$合法当且仅当$T'->T_{i}$)的“链树”,同时若满足了$T_{i}->T'$(即当前决定儿子状态的点在$T_{i}$中对应的点为叶子)就停止枚举
    考虑这一做法的时间复杂度:
    当一棵“链树”最深的节点有兄弟,此时不妨视为两棵,这就保证每一棵链树仅被分入4类中的一类
    时间复杂度即所有“链树”被划分的次数之和,而每一次划分可以看作“删除”掉当前正在处理的节点,显然这些删除不会重复,因此划分即删除的次数不超过$o(n)$,总复杂度即为$o(n)$
     
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2000005
     4 vector<int>v[N];
     5 int V,T,t,n,m,r[N],ls[N],rs[N],tot[N];
     6 bool pd(int k){
     7     if (!tot[k])return 1;
     8     if ((!tot[rs[k]])&&(pd(ls[k])))return 1;
     9     if ((!tot[ls[k]])&&(pd(rs[k])))return 1;
    10     return 0;
    11 }
    12 bool dfs(){
    13     bool v0=0,v1=0,v2=0,v3=0;
    14     for(int i=0;i<v[T].size();i++){
    15         if (!tot[v[T][i]])return 0;
    16         if ((ls[v[T][i]])&&(!tot[rs[v[T][i]]])&&(rs[v[T][i]]))v0=1;
    17         if ((ls[v[T][i]])&&(!tot[ls[v[T][i]]])&&(ls[v[T][i]]))v1=1;
    18         if ((rs[v[T][i]])&&(!tot[rs[v[T][i]]])&&(rs[v[T][i]]))v2=1;
    19         if ((rs[v[T][i]])&&(!tot[ls[v[T][i]]])&&(ls[v[T][i]]))v3=1;
    20     }
    21     if ((!v0)||(!v1)||(!v2)||(!v3))return 1;
    22     v[T+1].clear();
    23     for(int i=0;i<v[T].size();i++)
    24         if ((ls[v[T][i]])&&(!tot[rs[v[T][i]]])&&(rs[v[T][i]]))v[T+1].push_back(ls[v[T][i]]);
    25     T++;
    26     if (dfs())return 1;
    27     T--;
    28     v[T+1].clear();
    29     for(int i=0;i<v[T].size();i++)
    30         if ((ls[v[T][i]])&&(!tot[rs[v[T][i]]])&&(!rs[v[T][i]]))v[T+1].push_back(ls[v[T][i]]);
    31     T++;
    32     if (dfs())return 1;
    33     T--;
    34     v[T+1].clear();
    35     for(int i=0;i<v[T].size();i++)
    36         if ((rs[v[T][i]])&&(!tot[ls[v[T][i]]])&&(ls[v[T][i]]))v[T+1].push_back(rs[v[T][i]]);
    37     T++;
    38     if (dfs())return 1;
    39     T--;
    40     v[T+1].clear();
    41     for(int i=0;i<v[T].size();i++)
    42         if ((rs[v[T][i]])&&(!tot[ls[v[T][i]]])&&(!ls[v[T][i]]))v[T+1].push_back(rs[v[T][i]]);
    43     T++;
    44     if (dfs())return 1;
    45     T--;
    46     return 0;
    47 }
    48 int main(){
    49     freopen("surreal.in","r",stdin);
    50     freopen("surreal.out","w",stdout);
    51     scanf("%d",&t);
    52     while (t--){
    53         scanf("%d",&m);
    54         V=0;
    55         for(int i=1;i<=m;i++){
    56             scanf("%d",&n);
    57             r[i]=V+1;
    58             for(int j=1;j<=n;j++){
    59                 scanf("%d%d",&ls[j+V],&rs[j+V]);
    60                 if (ls[j+V])ls[j+V]+=V;
    61                 if (rs[j+V])rs[j+V]+=V;
    62                 tot[j+V]=(ls[j+V]>0)+(rs[j+V]>0);
    63             }
    64             V+=n;
    65             if (!pd(r[i])){
    66                 V-=n;
    67                 i--;
    68                 m--;
    69             }
    70         }
    71         T=0;
    72         v[0].clear();
    73         for(int i=1;i<=m;i++)v[0].push_back(r[i]);
    74         if (dfs())printf("No
    ");
    75         else printf("Almost Complete
    ");
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    数据结构实验之栈与队列四:括号匹配(SDUT 2134)
    从 s 点到 t 点的最短路(简单模板)(迪杰斯特拉)
    畅通工程续(HDU 1874)(简单最短路)
    Til the Cows Come Home ( POJ 2387) (简单最短路 Dijkstra)
    顺序表应用7:最大子段和之分治递归法(SDUT 3664)
    Java面向对象4(P~U)
    House Lawn Kattis
    Jumbled String (Kattis
    队列详解及java实现
    栈详解及java实现
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13546250.html
Copyright © 2011-2022 走看看