Topic Link
https://atcoder.jp/contests/agc014/tasks/agc014_e
answer
Tree cross over on the practice exam did not think that can be retired. . .
First there is a huge said to be difficult to write \ (O (n \ log ^ 3n) \) tree sectional + Tree Tree approach sets:
for each red edge \ ((U, V) \) , two trees to blue path between points \ (1 + \) , and then select a value of each \ (1 \) sides, to find the red edge covering it and then put the \ (1 \) side edged red cut off, then remove the effects of red edge.
Here's positive solutions.
Still above ideas, and then found that the former is assumed broken \ ((i-1) \ ) set Unicom block formed after the Blue edges are \ (B_i \) , even from the \ (I \) section to the second \ (n-\) communication block is formed after the red stripe sets of edges is \ (R_i \) , then the answer is YES
if and only if for any \ (2 \ Le I \ Le n-\) , \ (R_i = B_i \) .
Thus obtained may be converted: FIG beginning on which \ (n-\) points \ (2 (n-1) \) edges, two edges overlap when put shrunk connecting two points with a bit, Q last whole can shrink to a point.
Heuristic be merged. Maintaining the current queue weight all sides, and each point adjacent points on all sides of FIG. Each time an edge extracted from the queue, then the edge point is smaller degree of all transferred to a large degree point. So if we can repeat \ ((n-1) \ ) times, the answer is YES
, otherwise NO
. Adjacent points can be used set
to maintain, the top chart can be used map
to maintain.
Time complexity \ (O (n-\ log ^ 2N) \) .
Code
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<utility>
#define pii pair<int,int>
#define mkpr make_pair
using namespace std;
const int N = 1e5;
multiset<int> ae[N+3];
map<pii,int> g;
queue<pii> que;
int n;
void insertedge(int u,int v)
{
if(u==v) return;
if(u>v) swap(u,v);
ae[u].insert(v); ae[v].insert(u);
g[mkpr(u,v)]++;
if(g[mkpr(u,v)]==2) {que.push(mkpr(u,v));}
}
void deleteedge(int u,int v)
{
ae[v].erase(ae[v].find(u));
if(u>v) swap(u,v);
if(g.count(mkpr(u,v))) {g.erase(mkpr(u,v));}
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=2*(n-1); i++)
{
int u,v; scanf("%d%d",&u,&v);
insertedge(u,v);
}
for(int i=1; i<n; i++)
{
while(1)
{
if(que.empty()) {puts("NO"); return 0;}
int u = que.front().first,v = que.front().second; que.pop();
if(!g.count(mkpr(u,v))) {continue;}
if(ae[u].size()<ae[v].size()) swap(u,v);
for(set<int>::iterator i=ae[v].begin(); i!=ae[v].end(); i++)
{
int x = *i;
deleteedge(v,x);
insertedge(u,x);
}
break;
}
}
puts("YES");
return 0;
}