[zoj 3990]树方程
记$副(吨)$为树$T$的深度(根节点深度为0),则有$ \开始{病例} dep(A/B)=\最大(副(甲)、副(乙))\ \副(甲)=副(甲)副(乙)结束{病例}
考虑加元中最深的点,对其来源于$AX$还是$BY$分类讨论(不妨假设是前者),再取出其深度为$副(甲)$的祖先,那么$X$即只能取该祖先的子树
确定$X$后,求出$AX$并在加元中去掉,再类似地求出$Y$并判定即可
过程中需要实现一个树同构的判定,简单哈希即可
时间复杂度为$o(n\log n)$,可以通过
(实现可能略微有一些繁琐,由于无法提交并不保证代码正确,仅供参考)
1 #包括息税前利润/标准利润.h
2使用命名空间标准;
3 #定义N 100005
4 #定义mod 998244353
5 #定义陆线(landlines的缩写)长
6 int t,num[11],seed[N];
7 mapint,矢量垫子
8 mapint,矢量:迭代器它;
9 int read(){ 0
10 int x=0;
11 char c=getchar();
12 while((c ' 0 ')| |(c ' 9 ')c=getchar();
13 while((c=' 0 ')(c=' 9 '){ 0
14 x=x * 10c-' 0 ';
15c=getchar();
16 }
17返回x;
18 }
19无效写入(int x,char c=' \ 0 '){ 0
20 while(x){ 0
[num[0]]=x;
22 x/=10;
23 }
24如果(!num[0])放入char(' 0 ');
25 while(num[0])放char(num[num[0]-]' 0 ');
26普特查尔(c );
27 }
28结构树{
29 int n,rt,mx,fa[N],dep[N],sz[N],f[N];
30矢量[N];
31 bool运算符==(const Tree T)const{
32返回(SZ[rt]==t . SZ[t . rt])(f[rt]==t . f[t . rt]);
33 }
34 void Read(){ 0
35表示(int I=1;I=n;.clear();
36表示(int I=1;I=n;I){ 0
37 int x=read();
38如果(!x)rt=I;
39 else v[x].push _ back(I);
40 }
41 }
42 void Write(){ 0
43表示(int I=1;在;i )write(fa[i],' ');
44写(fa[n],' \ n ');
45 }
46 void dfs(int k,int s){ 0
47 dep[k]=s,SZ[k]=f[k]=1;
48表示(int I=0;四k .size();I){ 0
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]]*种子[SZ[v[k][I]])% mod;
52 }
53 }
54 void build(){ 0
55 fa[rt]=0,dfs(rt,0);
56 MX=0;
57表示(int I=1;I=n;i )mx=max(mx,dep[I]);
58 }
59 void get(Tree T,int k,int f){ 0
60 int id=T.n
61辆电视.clear();
62中频电视.push _ back(id);
63表示(int I=0;四k .size();i )get(T,v[k][i],id);
64 }
65 }A、B、C、X、Y、T、T0;
66无效mul(树A、树b、树T){ 0
67 T.n=A.n*B.n,t . rt=(a . rt-1)* b . n . 1;
68表示(int I=1;i=T.n电视clear();
69表示(int I=1;i=A.nI){ 0
70表示(int j=0;jA.v[i].size();(j)t . v[(I-1)* b . n . 1]。push _ back((a . v[I][j]-1)* b . n . 1);
71表示(int j=1;j=B.nj)
72表示(int k=0;kB.v[j].size();(k)t . v[(I-1)* b . n . j].push _ back((I-1)* b . n . b . v[j][k]);
73 }
74 }
75牛十二月(树甲、树乙、树丁){ 0
垫子。clear();
77表示(int I=0;人工授精size();一)mat[A.f[A.v[A.rt][i]].推回;
78 T.n=T.rt=1,T.v[1]。clear();
79表示(int I=0;iB.v .size();I){ 0
80 int x=b . f[b . v[b . rt][I]];
81 if (mat[x]).empty())返回0;
82垫[x].pop _ back();
83 }
84英镑。begin();它!=垫子。end();it){ 0
85矢量ntv=(*)it .第二;
86表示(int I=0;四.size();i )A.get(T,v[i],1);
87 }
88返回1;
89 }
90 bool calc(){ 0
91个国际位置;
92表示(int I=0;i=C.n(一)
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.nC.n)返回0;
97 mul(A,X,T),T . build();
98 if(!dec(C,T,T0))返回0;
99 T0。build();
100表示(int I=0;i=T0.n(一)
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)返回0;
105 mul(B,Y,T),T . build();
106返回T==T0
107 }
108 int main(){ 0
109 srand(时间(0));
110表示(int I=0;iN;(一)
111表示(int j=0;j60j)种子[i]=((种子[I]1)rand()% 2)% mod;
112t=read();
113 while(t-){ 0
114 A.n=read(),B.n=read(),c . n=read();
115 A。读(),B。读()、C。读();
116 A.build(),B.build(),c . build();
117 if(calc()){ 0
118写(X.n ' '),写(Y.n ',\ n ');
119 X.Write(),Y . Write();
120继续;
121 }
122互换(甲、乙);
123 if(!calc())printf('不可能\ n ');
124 else{
125写(Y.n ' '),写(X.n ',\ n ');
126 Y.Write(),X . Write();
127 }
128 }
129返回0;
130 }
查看代码
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/52100.html