【AGC014E】Blue and Red Tree
Description
给定一棵\(n\)个节点的蓝边树,再给定一棵\(n\)个节点的红边树。请通过若干次操作将蓝树变成红树。操作要求和过程如下:
1.选定一条边全为蓝色的路径;
2.将路径上的一条蓝边断开,并将路径的两个端点之间连一条红边。
问能否实现目标。
Solution
我们发现这个过程只会做恰好\(n-1\)次,因为每次都会减少一条蓝边、增加一条红边。
考虑红树上的一条边\((u,v)\),显然在蓝树上操作时,我们选择了一条以\(u\)和\(v\)为端点的路径,才造就了这条边。因此红树上的每条边和蓝树上的每次操作一一对应。
我们相当于要以某种顺序执行这些操作:对于操作\((u,v)\),保证操作前\(u\)和\(v\)连通,然后我们断开\(u\)到\(v\)路径上的一条边。问所有操作能否执行完。
如果我们要执行一个操作A,那么对于当下该路径上的所有边,我们只能断开只有A占用的边。形式化地讲,如果对于每一个未执行操作,都将路径上的边+1;那么当前我们只能断开边权为1的边。
我们想用树剖的方式维护并模拟这个操作,但这非常难实现。因为寻找边权为1的边这个操作,或许还需要树套树来维护,非常麻烦。
正难则反,考虑整个过程反向进行:
对于最后一次操作,树上一定只剩下一条边\((u,v)\),且最后一次操作也是\((u,v)\)。考虑倒数第二次操作,它要么是\((u,z)\),\(z\)是从最后一次操作的\((u,v)\)这条边延伸出的另一条边\((v,z)\),要么是另成的一条独立的边\((x,y)\).....
手玩一会,我们发现:如果把两棵树建在一起,那么每次可操作的边,就是两棵树中都存在的边。操作完之后,我们把操作边的两个端点缩点,继续重复上述操作。如果操作能够执行恰好\(n-1\)次,则有解,否则无解。
接下来关键是怎么实现。我们根据想的方法,将两棵树实实在在地建在一起。用\(n\)个set维护每个点的出边到达点,用一个map维护两两点之间边的数量。如果某两个点之间的连边数量等于2,则肯定这条边在两棵树中间都出席那了,我们将这两个点组成的边塞进队列里,表示这个队列里的边在当前都可以操作。接下来,我们不断从队头拿出边,进行缩点操作:启发式合并set,删边或加边直接操作set和map就好。
时间复杂度\(\mathcal O(n \log^2 n)\)
Code
#include <cstdio>
#include <set>
#include <queue>
#include <map>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef set<int> si;
typedef set<int>::iterator sit;
const int N=100005;
int n;
int bl[N];
si s[N];
queue<pii> q;
map<ll,int> g;
inline void swap(int &x,int &y){
x^=y^=x^=y;
}
int find(int u){
return bl[u]==u?u:(bl[u]=find(bl[u]));
}
inline ll getID(int x,int y){
if(x>y) swap(x,y);
return 1ll*n*y+x;
}
void addEdge(int u,int v){
s[u].insert(v);
s[v].insert(u);
ll eid=getID(u,v);
int t=g[eid]+1;
g[eid]++;
if(t==2)
q.push(mp(u,v));
}
void removeEdge(int u,int v){
s[u].erase(v);
s[v].erase(u);
g.erase(getID(u,v));
}
void readData(){
scanf("%d",&n);
int u,v;
for(int i=1;i<=(n-1)<<1;i++){
scanf("%d%d",&u,&v);
addEdge(u,v);
}
}
bool solve(){
for(int i=1;i<=n;i++) bl[i]=i;
for(int i=1;i<n;i++){
int u,v;
if(q.empty())
return false;
u=q.front().first;
v=q.front().second;
q.pop();
u=find(u);
v=find(v);
if(s[u].size()>s[v].size())
swap(u,v);
bl[u]=v;
removeEdge(u,v);
for(sit i=s[u].begin(),j;i!=s[u].end();i=j){
j=i;
j++;
int x=*i;
x=find(x);
removeEdge(u,x);
addEdge(v,x);
}
}
return true;
}
int main(){
readData();
puts(solve()?"YES":"NO");
return 0;
}
【AGC014E】Blue and Red Tree的更多相关文章
- 【AGC014E】Blue and Red Tree 并查集 启发式合并
题目描述 有一棵\(n\)个点的树,最开始所有边都是蓝边.每次你可以选择一条全是蓝边的路径,删掉其中一条,再把这两个端点之间连一条红边.再给你一棵树,这棵树的所有边都是红边,问你最终能不能把原来的树变 ...
- 【CF1425B】 Blue and Red of Our Faculty! 题解
原题链接 简要翻译: 有一个连通图,A和B同时从点1出发,沿不同的路径前进.原本,图上的每一条边都是灰色的.A将经过的边涂成红色,B将经过的边涂成蓝色的.每个回合每个人只能走灰色的边.当某个回合中不存 ...
- 【BZOJ2959】长跑(Link-Cut Tree,并查集)
[BZOJ2959]长跑(Link-Cut Tree,并查集) 题面 BZOJ 题解 如果保证不出现环的话 妥妥的\(LCT\)傻逼题 现在可能会出现环 环有什么影响? 那就可以沿着环把所有点全部走一 ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- 【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)
[BZOJ2816][ZJOI2012]网络(Link-Cut Tree) 题面 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相 ...
- 【CF434E】Furukawa Nagisa's Tree 点分治
[CF434E]Furukawa Nagisa's Tree 题意:一棵n个点的树,点有点权.定义$G(a,b)$表示:我们将树上从a走到b经过的点都拿出来,设这些点的点权分别为$z_0,z_1... ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- 【SPOJ】QTREE7(Link-Cut Tree)
[SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
随机推荐
- Linux中执行脚本参数获取
Linux中变量$[#,@,0,1,2,*,$,?]含义 $# 是传给脚本的参数个数 $0 是脚本本身的名字 $1 是传递给该shell脚本的第一个参数 $2 是传递给该shell脚本的第二个参数 $ ...
- .NetCore实践篇:分布式监控系统zipkin踩坑之路(二)
前言 <牧神记>有一句话说的好,破心中神.当不再对分布式,微服务,CLR畏惧迷茫的时候,你就破了心中神. zipkin复习 第一篇: .Net架构篇:思考如何设计一款实用的分布式监控系统? ...
- 【亲测有效】运行docker ps 出现Got permission denied问题的解决方案
问题描述 今天在运行 docker ps 命令的时候出现如下问题: Got permission denied while trying to connect to the Docker daemon ...
- Ubuntu16.04下使用rdesktop命令远程连接windows机器
前段时间在本机安装了ubuntu16.04桌面版,后来需要远程连接一台win10系统的跳转机,下面介绍使用rdesktop命令远程连接windows机器的操作记录:1)首先安装rdesktop工具 k ...
- Docker容器学习梳理 - 基础知识(2)
之前已经总结了Docker容器学习梳理--基础知识(1),但是不够详细,下面再完整补充下Docker学习的一些基础. Docker是个什么东西 Docker是一个程序运行.测试.交付的开放平台,Doc ...
- 分布式监控系统Zabbix--完整安装记录(7)-使用percona监控MySQL
前面已经介绍了分布式监控系统Zabbix-3.0.3-完整安装记录(2)-添加mysql监控,但是没有提供可以直接使用的Key,太过简陋,监控效果不佳.要想更加仔细的监控Mysql,业内同学们都会选择 ...
- Bing词典案例分析
一.调研评测 Bug 1 : 当鼠标移动到可点击的地方的时候,光标的样子并没有变成手指状而是插入符号状.这影响了用户对按钮是否可用的判断,也会让用户在一定程度上不适应,不利于软件的长期发展. Bug ...
- Linux 检查磁盘性能速度
1. hdparm 工具: hdparm –t 设备名(/dev/sda1) 2. time dd if=/dev/zero of=/tmp/test.dat bs=1G count=1
- Node 表单query
//#使用nodejs编写动态的web服务器//1:加载需要模块 fs http urlconst fs = require("fs");const http = require( ...
- ERP启动会
一个信念: 只许成功,不许失败. 二个原则: 第一个原则是“业务为主,IT为辅”的实施原则: 第二个原则是“循序渐进,持续改善”的工作原则. 三点要求: 第一点,各分公司.各部门的负责人要将ERP信息 ...