#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define fill( x, y ) memset( x, y, sizeof x )
#define copy( x, y ) memcpy( x, y, sizeof x )
using namespace std;
 
typedef long long LL;
typedef pair < int, int > pa;
 
inline int read()
{
	int sc = 0, f = 1; char ch = getchar();
	while( ch < '0' || ch > '9' ) { if( ch == '-' ) f = -1; ch = getchar(); }
	while( ch >= '0' && ch <= '9' ) sc = sc * 10 + ch - '0', ch = getchar();
	return sc * f;
}
 
const int MAXN = 100005;
const int INF = 0x3f3f3f3f;
 
int dfn[MAXN], tim, dep[MAXN], fa[MAXN], bl[MAXN], size[MAXN], n;
pa mn[MAXN << 2];
set < pa > S[MAXN << 2];
vector < int > G[MAXN];
 
inline void dfs(int x)
{
	size[ x ] = 1;
	for( auto y : G[ x ] ) if( y ^ fa[ x ] )
	{
		fa[ y ] = x;
		dep[ y ] = dep[ x ] + 1;
		dfs( y );
		size[ x ] += size[ y ];
	}
}
 
inline void dfs2(int x, int c)
{
	dfn[ x ] = ++tim; bl[ x ] = c;
	int k = 0;
	for( auto y : G[ x ] ) if( y ^ fa[ x ] ) if( size[ y ] > size[ k ] ) k = y;
	if( !k ) return ;
	dfs2( k, c );
	for( auto y : G[ x ] ) if( y ^ fa[ x ] ) if( y ^ k ) dfs2( y, y );
}
 
inline void pushup(int x) { mn[ x ] = min( mn[ x << 1 ], mn[ x << 1 | 1 ] ); mn[ x ].xx += S[ x ].size(); }
 
inline void build(int x, int l, int r)
{
	mn[ x ].yy = l;
	if( l == r ) return ;
	int mid = l + r >> 1;
	build( x << 1, l, mid ); build( x << 1 | 1, mid + 1, r );
}
 
inline void insert(int x, int l, int r, int ql, int qr, pa v)
{
	if( l == ql && r == qr ) { S[ x ].insert( v ); mn[ x ].xx++; return ; }
	int mid = l + r >> 1;
	if( qr <= mid ) insert( x << 1, l, mid, ql, qr, v );
	else if( ql > mid ) insert( x << 1 | 1, mid + 1, r, ql, qr, v );
	else insert( x << 1, l, mid, ql, mid, v ), insert( x << 1 | 1, mid + 1, r, mid + 1, qr, v );
	pushup( x );
}
 
inline void add(int x, int y)
{
	int tx = x, ty = y;
	while( bl[ tx ] ^ bl[ ty ] )
	{
		if( dep[ bl[ tx ] ] < dep[ bl[ ty ] ] ) swap( tx, ty );
		insert( 1, 2, n, dfn[ bl[ tx ] ], dfn[ tx ], mp( x, y ) );
		tx = fa[ bl[ tx ] ];
	}
	if( dfn[ tx ] > dfn[ ty ] ) swap( tx, ty );
	if( tx ^ ty ) insert( 1, 2, n, dfn[ tx ] + 1, dfn[ ty ], mp( x, y ) );
}
 
inline void erase(int x, int l, int r, int ql, int qr, pa v)
{
	if( l == ql && r == qr ) { S[ x ].erase( v ); mn[ x ].xx--; return ; }
	int mid = l + r >> 1;
	if( qr <= mid ) erase( x << 1, l, mid, ql, qr, v );
	else if( ql > mid ) erase( x << 1 | 1, mid + 1, r, ql, qr, v );
	else erase( x << 1, l, mid, ql, mid, v ), erase( x << 1 | 1, mid + 1, r, mid + 1, qr, v );
	pushup( x );
}
 
inline void del(int x, int y)
{
	int tx = x, ty = y;
	while( bl[ tx ] ^ bl[ ty ] )
	{
		if( dep[ bl[ tx ] ] < dep[ bl[ ty ] ] ) swap( tx, ty );
		erase( 1, 2, n, dfn[ bl[ tx ] ], dfn[ tx ], mp( x, y ) );
		tx = fa[ bl[ tx ] ];
	}
	if( dfn[ tx ] > dfn[ ty ] ) swap( tx, ty );
	if( tx ^ ty ) erase( 1, 2, n, dfn[ tx ] + 1, dfn[ ty ], mp( x, y ) );
}
 
inline void GG()
{
	puts( "NO" );
	exit( 0 );
}
 
inline pa query(int x, int l, int r, int p)
{
	if( S[ x ].size() ) return *S[ x ].begin();
	int mid = l + r >> 1;
	if( p <= mid ) return query( x << 1, l, mid, p );
	return query( x << 1 | 1, mid + 1, r, p );
}
 
inline void modify(int x, int l, int r, int p)
{
	if( l == r ) { mn[ x ].xx = INF; return ; }
	int mid = l + r >> 1;
	if( p <= mid ) modify( x << 1, l, mid, p );
	else modify( x << 1 | 1, mid + 1, r, p );
	pushup( x );
}
 
int main()
{
#ifdef wxh010910
	freopen( "data.in", "r", stdin );
#endif
	n = read();
	for( int i = 1, x, y ; i < n ; i++ ) x = read(), y = read(), G[ x ].pb( y ), G[ y ].pb( x );
	dfs( 1 ); dfs2( 1, 1 );
	build( 1, 2, n );
	for( int i = 1, x, y ; i < n ; i++ ) add( read(), read() );
	for( int i = 1 ; i < n ; i++ )
	{
		if( mn[ 1 ].xx ^ 1 ) GG();
		int p = mn[ 1 ].yy;
		pa t = query( 1, 2, n, p );
		del( t.xx, t.yy ); modify( 1, 2, n, p );
	}
	return puts( "YES" ), 0;
}


Measured memory_bytes: 124416