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 搞出来轻重儿子- 求每个节点的子树上有 ...
随机推荐
- anaconda中的包如何传到pycharm中使用?
在pycharm的setting中设置 在project interpreter 中的 existing environment 中选择 anaconda3安装目录下的的 python.exe 就可以 ...
- js FileReader 笔记
以上传图片为例 通过input type='file' 上传完成图片后,获取图片 $('#input').files[0] var reader = new FileReader(); read ...
- Python3 zip() 函数
描述 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存. 我们可以使用 list() 转换来输出列表. 如果 ...
- 插件使用一树形插件---zTree一zTree异步加载
zTree 可以实现异步加载.异步加载可以让初次加载速度快,带来好的用户体验. 异步加载 官方源码中的demo提示了例子.例子是采用php语言. 在java语言中,zTree如何与Servlet结合呢 ...
- C#学习-字段
字段的定义由3部分组成,访问修饰符.字段的类型和字段的名称.以下是 public class Person { //姓名,类型为字符串类型 private string name; //年龄,类型为i ...
- thinkphp5验证码使用
simple 控制器中 /** * 生成验证码 * @param viod */ public function verify() { $captcha = new \think\captcha\Ca ...
- Pytorch学习笔记
非线性回归问题的参数求解,反向求导基本流程.Variable 计算时, 它在后台一步步默默地搭建着一个庞大的系统, 叫做计算图, computational graph. 这个图将所有的计算步骤 (节 ...
- Python_冒泡排序
从小到大的排序:(最前面的数和一步步和后面的数比较,如果大于则交换,如果不大于则继续循环) 方法1: data = [65, 1, 45, 77, 3, 9, 43, 23, 7, 53, 213, ...
- Codeforces 1045C Hyperspace Highways (看题解) 圆方树
学了一下圆方树, 好神奇的东西呀. #include<bits/stdc++.h> #define LL long long #define fi first #define se sec ...
- siege压力测试工具安装和介绍
Siege是linux下的一个web系统的压力测试工具,支持多链接,支持get和post请求,可以对web系统进行多并发下持续请求的压力测试. 安装 Siege #wget http://www.jo ...