[zoj3990]Tree Equation

记$dep(T)$为树$T$的深度(根节点深度为0),则有$egin{cases}dep(A+B)=max(dep(A),dep(B))\dep(Acdot B)=dep(A)+dep(B)end{cases}$

考虑$C$中最深的点,对其来源于$AX$还是$BY$分类讨论(不妨假设是前者),再取出其深度为$dep(A)$的祖先,那么$X$即只能取该祖先的子树

确定$X$后,求出$AX$并在$C$中去掉,再类似地求出$Y$并判定即可

过程中需要实现一个树同构的判定,简单哈希即可

时间复杂度为$o(nlog n)$,可以通过

(实现可能略微有一些繁琐,由于无法提交并不保证代码正确,仅供参考)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 #define mod 998244353
  5 #define ll long long
  6 int t,num[11],seed[N];
  7 map<int,vector<int> >mat;
  8 map<int,vector<int> >::iterator it;
  9 int read(){
 10     int x=0;
 11     char c=getchar();
 12     while ((c<'0')||(c>'9'))c=getchar();
 13     while ((c>='0')&&(c<='9')){
 14         x=x*10+c-'0';
 15         c=getchar();
 16     }
 17     return x;
 18 }
 19 void write(int x,char c=''){
 20     while (x){
 21         num[++num[0]]=x%10;
 22         x/=10;
 23     }
 24     if (!num[0])putchar('0');
 25     while (num[0])putchar(num[num[0]--]+'0');
 26     putchar(c);
 27 }
 28 struct Tree{
 29     int n,rt,mx,fa[N],dep[N],sz[N],f[N];
 30     vector<int>v[N];
 31     bool operator == (const Tree &T)const{
 32         return (sz[rt]==T.sz[T.rt])&&(f[rt]==T.f[T.rt]);
 33     }
 34     void Read(){
 35         for(int i=1;i<=n;i++)v[i].clear();
 36         for(int i=1;i<=n;i++){
 37             int x=read();
 38             if (!x)rt=i;
 39             else v[x].push_back(i);
 40         }
 41     }
 42     void Write(){
 43         for(int i=1;i<n;i++)write(fa[i],' ');
 44         write(fa[n],'
');
 45     }
 46     void dfs(int k,int s){
 47         dep[k]=s,sz[k]=f[k]=1;
 48         for(int i=0;i<v[k].size();i++){
 49             fa[v[k][i]]=k,dfs(v[k][i],s+1);
 50             sz[k]+=sz[v[k][i]];
 51             f[k]=(f[k]+(ll)f[v[k][i]]*seed[sz[v[k][i]]])%mod;
 52         }
 53     }
 54     void build(){
 55         fa[rt]=0,dfs(rt,0);
 56         mx=0;
 57         for(int i=1;i<=n;i++)mx=max(mx,dep[i]);
 58     }
 59     void get(Tree &T,int k,int f){
 60         int id=++T.n;
 61         T.v[id].clear();
 62         if (f)T.v[f].push_back(id); 
 63         for(int i=0;i<v[k].size();i++)get(T,v[k][i],id);
 64     }
 65 }A,B,C,X,Y,T,T0;
 66 void mul(Tree &A,Tree &B,Tree &T){
 67     T.n=A.n*B.n,T.rt=(A.rt-1)*B.n+1;
 68     for(int i=1;i<=T.n;i++)T.v[i].clear();
 69     for(int i=1;i<=A.n;i++){
 70         for(int j=0;j<A.v[i].size();j++)T.v[(i-1)*B.n+1].push_back((A.v[i][j]-1)*B.n+1);
 71         for(int j=1;j<=B.n;j++)
 72             for(int k=0;k<B.v[j].size();k++)T.v[(i-1)*B.n+j].push_back((i-1)*B.n+B.v[j][k]);
 73     }
 74 }
 75 bool dec(Tree &A,Tree &B,Tree &T){
 76     mat.clear();
 77     for(int i=0;i<A.v[A.rt].size();i++)mat[A.f[A.v[A.rt][i]]].push_back(A.v[A.rt][i]);
 78     T.n=T.rt=1,T.v[1].clear();
 79     for(int i=0;i<B.v[B.rt].size();i++){
 80         int x=B.f[B.v[B.rt][i]];
 81         if (mat[x].empty())return 0;
 82         mat[x].pop_back();
 83     }
 84     for(it=mat.begin();it!=mat.end();it++){
 85         vector<int>v=(*it).second;
 86         for(int i=0;i<v.size();i++)A.get(T,v[i],1);
 87     }
 88     return 1;
 89 }
 90 bool calc(){
 91     int pos;
 92     for(int i=0;i<=C.n;i++)
 93         if (C.dep[i]==C.mx)pos=i;
 94     while (C.dep[pos]!=A.mx)pos=C.fa[pos];
 95     X.n=0,X.rt=1,C.get(X,pos,0),X.build();
 96     if ((ll)A.n*X.n>C.n)return 0;
 97     mul(A,X,T),T.build();
 98     if (!dec(C,T,T0))return 0;
 99     T0.build();
100     for(int i=0;i<=T0.n;i++)
101         if (T0.dep[i]==T0.mx)pos=i;
102     while (T0.dep[pos]!=B.mx)pos=T0.fa[pos];
103     Y.n=0,Y.rt=1,T0.get(Y,pos,0),Y.build();
104     if ((ll)B.n*Y.n!=T0.n)return 0;
105     mul(B,Y,T),T.build();
106     return T==T0;
107 }
108 int main(){
109     srand(time(0));
110     for(int i=0;i<N;i++)
111         for(int j=0;j<60;j++)seed[i]=((seed[i]<<1)+rand()%2)%mod;
112     t=read();
113     while (t--){
114         A.n=read(),B.n=read(),C.n=read();
115         A.Read(),B.Read(),C.Read();
116         A.build(),B.build(),C.build();
117         if (calc()){
118             write(X.n,' '),write(Y.n,'
');
119             X.Write(),Y.Write();
120             continue;
121         }
122         swap(A,B);
123         if (!calc())printf("Impossible
");
124         else{
125             write(Y.n,' '),write(X.n,'
');
126             Y.Write(),X.Write();
127         }
128     }
129     return 0;
130 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/15471284.html