[AT2377] [agc014_e] Blue and Red Tree

题目链接

AtCoder:https://agc014.contest.atcoder.jp/tasks/agc014_e

洛谷:https://www.luogu.org/problemnew/show/AT2377

Solution

秒了(O(n^2))不会优化是什么鬼...最后膜了大佬的题解才会写...

注意到最后一条边一定在蓝图上存在,在红图上也存在,那么我们可以找到任意一条这样的边,把两端的点合并起来,蓝图和红图都合并,剩下的是一个子问题,做(n-1)遍就好了,复杂度(O(n^2))

那么合并节点可以用并查集,然后每次暴力遍历点度小的那个点启发式合并就好了。

全程(STL)代码很恶心...注意并查集到处都要(find)一下,我就是挂的这里然后调了好久...

复杂度(O(nlog ^2 n))

#include<bits/stdc++.h>
using namespace std;

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('
');}

#define lf double
#define ll long long 
#define pb push_back

#define pii pair<int,int > 
#define mp make_pair
#define fr first
#define sc second

#define iter_map map<int,int > :: iterator
#define iter_vec vector<int > :: iterator 
#define iter_set set<int > :: iterator 

const int maxn = 5e5+10;
const int inf = 1e9;
const lf eps = 1e-8;

struct DSU {
	int fa[maxn];
	void init(int n) {for(int i=1;i<=n;i++) fa[i]=i;}
	int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
}dsu;

queue<pii > q;
set<int > e[maxn];
map<pii,int > s;
int n,d[maxn];

pii get(int x,int y) {return mp(min(x,y),max(x,y));}

void ins(int x,int y) {
	e[x].insert(y),e[y].insert(x);
	pii now=get(x,y);s[now]++;
	if(s[now]==2) q.push(now);
}

int main() {
	read(n);dsu.init(n);
	for(int i=1,x,y;i<n*2-1;i++) read(x),read(y),ins(x,y);
	for(int i=1,x,y;i<n;i++) {
		while(1) {
			if(q.empty()) {puts("NO");exit(0);}
			x=dsu.find(q.front().fr),y=dsu.find(q.front().sc);q.pop(); //记得find...
			if(x!=y) break;
		}
		if(e[x].size()>e[y].size()) swap(x,y);
		dsu.fa[x]=y,s.erase(get(x,y)),e[y].erase(x);
		for(iter_set it=e[x].begin();it!=e[x].end();it++) {
			int t=dsu.find(*it);
			if(t==y) continue;
			s.erase(get(x,t));ins(t,y);
			e[t].erase(x),e[x].erase(t);
		}
	}puts("YES");
	return 0;
}
原文地址:https://www.cnblogs.com/hbyer/p/10697401.html