题解:
考虑边分治的过程, 最后一定存在两条既在原树上出现,也在新树上出现的边。
我们一定是最后处理这条边,这样就可以合并这两个点变为子问题处理,直到最后只有一个点为止。
合并用启发式合并即可,时间复杂度 O(nlog2n) O ( n log 2 n ) 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e5+50;
int n, anc[N], sze[N];
struct E {
int x,y;
E() {}
E(int _x,int _y) {
x=min(_x,_y);
y=max(_x,_y);
}
friend inline bool operator <(const E &a,const E &b) {return a.x<b.x || (a.x==b.x && a.y<b.y);}
};
set <int> *be[N], *re[N];
set <E> all;
typedef set <int> ::iterator it_si;
typedef set <E> :: iterator it_se;
inline it_si nxt(it_si p) {return ++p;}
inline int ga(int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc[x]));}
inline int inc_b(int x,int y) {
be[x]->insert(y); be[y]->insert(x);
if(re[x]->find(y)!=re[x]->end()) all.insert(E(x,y));
}
inline int dec_b(int x,int y) {
be[x]->erase(y); be[y]->erase(x);
it_se t=all.find(E(x,y));
if(t!=all.end()) all.erase(t);
}
inline int inc_r(int x,int y) {
re[x]->insert(y); re[y]->insert(x);
if(be[x]->find(y)!=be[x]->end()) all.insert(E(x,y));
}
inline int dec_r(int x,int y) {
re[x]->erase(y); re[y]->erase(x);
it_se t=all.find(E(x,y));
if(t!=all.end()) all.erase(t);
}
int main() {
n=rd();
for(int i=1;i<=n;i++) sze[i]=1, anc[i]=i, be[i]=new set<int>, re[i]=new set<int>;
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
inc_b(x,y);
}
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
inc_r(x,y);
}
int cnt=0;
while((all.size())&&(++cnt)) {
int x=all.begin()->x, y=all.begin()->y;
all.erase(all.begin());
if(sze[x] < sze[y]) swap(x,y);
sze[x]+=sze[y]; dec_b(x,y); dec_r(x,y);
for(it_si it=be[y]->begin(); it!=be[y]->end(); ) {
int t=*it; it=nxt(it);
dec_b(y,t);
inc_b(x,t);
}
for(it_si it=re[y]->begin(); it!=re[y]->end(); ) {
int t=*it; it=nxt(it);
dec_r(y,t);
inc_r(x,t);
}
delete be[y]; delete re[y];
}
puts((cnt==n-1)?"YES":"NO");
}