AGC 014E.Blue and Red Tree(思路 启发式合并)
\(Description\)
给定两棵\(n\)个点的树,分别是由\(n-1\)条蓝边和\(n-1\)条红边组成的树。求\(n-1\)次操作后,能否把蓝树变成红树。
每次操作是,选择当前树上一条只由蓝边组成的简单路径\(u\to v\),删掉路径上的任意一条蓝边,然后在路径上任选两个点,在这两个点之间加一条红边。
\(n\leq10^5\)。
\(Solution\)
模拟一下样例二,就比较容易想到:
考虑能否从红树变回到蓝树。
我们每次要找到当前树上一条蓝边组成的路径\(u\to v\),设路径上任意一点是\(a\),不在路径上的一个点是\(b\)。如果当前\(a,b\)之间有红边相连,而\(b\)与路径上某点\(c\)在蓝树上有边,显然这条红边\((a,b)\)是可以通过删掉\((b,c)\)加入的,也就是现在我们在当前树上删掉边\((a,b)\),加入边\((b,c)\)。然后继续找蓝边路径继续扩展。
怎么实现这一过程呢?
对于整条蓝边组成的路径\(u\to v\),我们不需要管具体有哪些点,只需要知道\(b\)与\(u\to v\)之间既有一条红边,也有一条蓝边(不会有两条红边/蓝边啊,因为每次操作后也是一棵树),然后我们可以删掉这条红边,加入这条蓝边。边具体是哪条也不需要管,我们只需要知道\(b\)被加入了路径\(u\to v\)。
所以就可以用并查集实现。\(b\)被合并到路径\(u\to v\)前,要把与\(b\)相连的所有边连到路径\(u\to v\)(的代表点)上去,可以用启发式合并。
同时有红边和蓝边与路径相连,就是这条边出现了两次。所以我们把出现两次的边拿出来扩展就好了。
能扩展\(n-1\)次则可行,否则不行。
启发式合并然后用set维护出边,复杂度\(O(n\log^2n)\)。出边可以hash点对\((u,v)\)来维护,少一个\(\log\),懒得写了。。
//287ms 25472KB
#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=1e5+5;
int fa[N];
std::set<int> st[N];
std::pair<int,int> q[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
int Find(int x)
{
return x==fa[x]?x:fa[x]=Find(fa[x]);
}
int main()
{
const int n=read();
int h=0,t=0;
for(int i=n-1<<1; i; --i)
{
int u=read(),v=read();
// if(u>v) std::swap(u,v);
if(!st[u].count(v)) st[u].insert(v), st[v].insert(u);
else q[t++]=std::make_pair(u,v);
}
for(int i=1; i<=n; ++i) fa[i]=i;
while(h<t)
{
int x=Find(q[h].first),y=Find(q[h++].second);
if(st[x].size()<st[y].size()) std::swap(x,y);//x<-y
for(std::set<int>::iterator it=st[y].begin(); it!=st[y].end(); ++it)
if(*it!=x)
{
int u=x,v=*it;
st[v].erase(y);
// if(u>v) std::swap(u,v);
if(!st[u].count(v)) st[u].insert(v), st[v].insert(u);
else q[t++]=std::make_pair(u,v);
}
st[x].erase(y), fa[y]=x;
}
puts(t==n-1?"YES":"NO");
return 0;
}
AGC 014E.Blue and Red Tree(思路 启发式合并)的更多相关文章
- AT2377 Blue and Red Tree
AT2377 Blue and Red Tree 法一:正推 红色的边在蓝色的树上覆盖,一定每次选择的是覆盖次数为1的边的覆盖这条边的红色边连出来 覆盖次数可以树剖找到 这条红色边,可以开始的时候每个 ...
- AtCoder AGC014E Blue and Red Tree (启发式合并)
题目链接 https://atcoder.jp/contests/agc014/tasks/agc014_e 题解 完了考场上树剖做法都没想到是不是可以退役了... 首先有一个巨难写的据说是\(O(n ...
- AGC014E Blue and Red Tree
题意 There is a tree with \(N\) vertices numbered \(1\) through \(N\). The \(i\)-th of the \(N−1\) edg ...
- AtCoder Grand Contest 014 E:Blue and Red Tree
题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_e 题目翻译 有一棵有\(N\)个点的树,初始时每条边都是蓝色的,每次你可以选择一条由蓝色边构 ...
- 【AGC014E】Blue and Red Tree
Description 给定一棵\(n\)个节点的蓝边树,再给定一棵\(n\)个节点的红边树.请通过若干次操作将蓝树变成红树.操作要求和过程如下: 1.选定一条边全为蓝色的路径: 2.将路径上的一条蓝 ...
- [AT2377] [agc014_e] Blue and Red Tree
题目链接 AtCoder:https://agc014.contest.atcoder.jp/tasks/agc014_e 洛谷:https://www.luogu.org/problemnew/sh ...
- [atAGC014E]Blue and Red Tree
不断删除重边,然后将两个点的边集启发式合并(要考虑到两棵树),合并时发现重边就加入队列,最后判断是否全部删完即可 1 #include<bits/stdc++.h> 2 using nam ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- dsu on tree[树上启发式合并学习笔记]
dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有 ...
随机推荐
- kali访问宿主机Web页面解决方案
1.首先安装好PHPDVWA测试平台,将等级设置成low,kali中自带了python2.7.为了不再宿主机中修改python3.6,所以要利用kali来模访问宿主机中的Web页面.如果不进行配置修改 ...
- 论文阅读笔记六:FCN:Fully Convolutional Networks for Semantic Segmentation(CVPR2015)
今天来看一看一个比较经典的语义分割网络,那就是FCN,全称如题,原英文论文网址:https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn ...
- js基本类型和字符串的具体应用
变量 JavaScript 是一种弱类型语言,javascript的变量类型由它的值来决定. 定义变量需要用关键字 'var' var a = 123; var b = 'asd'; //同时定义多个 ...
- pp 总结一
1.JQ $.get() <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- sprintf补位
有的时候需要00001这样的字符串 来源却是Int的1 这个时候就可以用sprintf方法了 $i = 3; $a=sprintf("%08d", $i); echo $a; %0 ...
- 【Android】jar包Proguard混淆方法
本文章的前提条件是,读者已经掌握了正确导出jar包的技能. 1.拷贝Android项目中“proguard.cfg”文件到你指定的位置,并改名为“proguard.pro”,此步是为proguardg ...
- 1900型USB接口扫描枪设置虚拟串口模式提升扫描速度
在使用扫描枪的过程中,发现扫描二维码速度比较慢,不到100个字符,花了大概2-3秒的时间才完成显示,这个速度不能忍受啊.通过度娘,说是可以将USB键盘模式接收字符转换成虚拟串口接收,这样可以大大提高速 ...
- spark操作Kudu之写 - 使用DataFrame API
在通过DataFrame API编写时,目前只支持一种模式“append”.尚未实现的“覆盖”模式 import org.apache.kudu.spark.kudu._ import org.apa ...
- mysql-索引-日志
索引:基于元数据之上的在某个字段或多个字段取出来,索引是加速读操作的,但对写操作时有副作用的 BTree 索引:抽取出来重新排序,是左前缀索引每一个叶子结点到根结点的距离相同: 哈希索引:基于键查找值 ...
- HTML自定义滚动条(仿网易邮箱滚动条)转载
它是使用CSS中的伪元素来实现的,主要由以下三个来完成: 1. -webkit-scrollbar:定义滚动条的样式,如长宽. 2. -webkit-scrollbar-thumb:定义滚动条上滑块的 ...