トピックリンク
https://atcoder.jp/contests/agc014/tasks/agc014_e
問題の解決策
ツリーが引退することができるとは思いませんでした模擬試験に渡ります。。。
最初の書き込みが困難であると言わ巨大ある\(O(N ^ログ\ \)3N)を:ツリー断面+ツリーのツリー手法セット
それぞれ赤色エッジ用の\((U、V)\)、2つのツリー青経路点間の\(1 + \) 、その後各々の値を選択\を(1 \)側、それを覆う赤エッジを見つけ、次に配置する\を(1 \)側には、赤が切断エッジその後、赤のエッジの影響を取り除きます。
ここでは、正のソリューションです。
まだ考え上、及びその後前者が破損想定されることを見出し\を((I-1)\ ) ブルーエッジがされた後に形成されユニコムブロックを設定する(B_i \)\、偶数から\(Iは\)第二の部分\(N- \)通信ブロックがエッジの赤ストライプセットした後に形成されている\(R_iを\) 、次いで、答えはYES
場合にのみいずれかに対する場合\(2 \ルI \ルN- \) 、\(R_iを= B_i \)。
得られたが、変換することができる:上の図の開始\(N- \)ポイント\(2(N-1) \) 接続された2つの点が同じ点Qを置くために収縮するときのエッジ、両エッジが重なっ最後に全体がポイントに縮小することができます。
ヒューリスティックをマージします。現在のキューの体重を維持するすべての側面、図のすべての側面上の各点の隣接点。エッジがキューから抽出された各時間は、次いで、エッジ点が大きくポイントに転送されるすべての小さい程度です。我々は繰り返すことができますのであれば、\((N-1)\ ) 回、答えはYES
そうでない場合は、NO
隣接するポイントを使用することができますset
維持するために、トップチャートを使用することができますmap
維持します。
時間複雑\(O(N \ログ^ 2N)\) 。
コード
#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;
}