题目链接

\(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(思路 启发式合并)的更多相关文章

  1. AT2377 Blue and Red Tree

    AT2377 Blue and Red Tree 法一:正推 红色的边在蓝色的树上覆盖,一定每次选择的是覆盖次数为1的边的覆盖这条边的红色边连出来 覆盖次数可以树剖找到 这条红色边,可以开始的时候每个 ...

  2. AtCoder AGC014E Blue and Red Tree (启发式合并)

    题目链接 https://atcoder.jp/contests/agc014/tasks/agc014_e 题解 完了考场上树剖做法都没想到是不是可以退役了... 首先有一个巨难写的据说是\(O(n ...

  3. AGC014E Blue and Red Tree

    题意 There is a tree with \(N\) vertices numbered \(1\) through \(N\). The \(i\)-th of the \(N−1\) edg ...

  4. AtCoder Grand Contest 014 E:Blue and Red Tree

    题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_e 题目翻译 有一棵有\(N\)个点的树,初始时每条边都是蓝色的,每次你可以选择一条由蓝色边构 ...

  5. 【AGC014E】Blue and Red Tree

    Description 给定一棵\(n\)个节点的蓝边树,再给定一棵\(n\)个节点的红边树.请通过若干次操作将蓝树变成红树.操作要求和过程如下: 1.选定一条边全为蓝色的路径: 2.将路径上的一条蓝 ...

  6. [AT2377] [agc014_e] Blue and Red Tree

    题目链接 AtCoder:https://agc014.contest.atcoder.jp/tasks/agc014_e 洛谷:https://www.luogu.org/problemnew/sh ...

  7. [atAGC014E]Blue and Red Tree

    不断删除重边,然后将两个点的边集启发式合并(要考虑到两棵树),合并时发现重边就加入队列,最后判断是否全部删完即可 1 #include<bits/stdc++.h> 2 using nam ...

  8. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  9. dsu on tree[树上启发式合并学习笔记]

    dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有 ...

随机推荐

  1. 实现本地svn目录同步时,服务器的相应目录保持自动同步

    提交一个TEST文件夹 但是服务器上并没有显示 而新检出的目录却有 这个时候需要手动去update才会显示,而不可能每次都去update,所以,就用到配置自动更新 1.创建svn目录:mkdir /v ...

  2. 性能测试四十一:sql案例之慢sql配置、执行计划和索引

    MYSQL 慢查询使用方法MYSQL慢查询介绍分析MySQL语句查询性能的问题时候,可以在MySQL记录中查询超过指定时间的语句,我们将超过指定时间的SQL语句查询称为“慢查询”.MYSQL自带的慢查 ...

  3. 为什么访问json接口出现文件下载

    在IE9,10,11下,当服务器端返回数据格式为json,且明确设置Content-Type为”application/json;charset=utf-8“时,会提示文件下载.如图所示: 解决办法是 ...

  4. tomcat中浏览器重新选择下.就解决该问题了

  5. caffe入门-人脸检测1

    最近刚入门caffe,跟着视频做了一个简单人脸检测.包括人脸二分类模型+方框框出人脸. 人脸二分类模型 1. 收集数据 我用的是lfw数据集,总共有13233张人脸图片.非人脸数据有两种选择.1. 用 ...

  6. python练习册0005

    第 0005 题:你有一个目录,装了很多照片,把它们的尺寸变成都不大于 iPhone5 分辨率的大小. 本题用了几个os模块的命令, import os from PIL import Image p ...

  7. C/C++遍历二维数组,列优先(column-major)比行优先(row-major)慢,why?

    C/C++遍历二维数组,列优先(column-major)比行优先(row-major)慢,why? 简单粗暴的答案:存在Cache机制! 稍微啰嗦一点:CPU访问内存(读/写,遍历数组的话主要是读) ...

  8. 解决notepad++64位没有plugin manager的问题

    安装了最新的notepad++版本发现没有插件管理器,很难受. 后来上官网发现了这样一句话 Note that the most of plugins (including Plugin Manage ...

  9. Junit4 IDEA测试学习一

    1.Junit4 下载 https://github.com/junit-team/junit4/releases 4.12 还需要还导入hamcrest-core-1.3.jar 2.IDEA Te ...

  10. android开发默认图标怎么换?

    首先要在资源文件放入想换的图标图片拖到drawable-XX文件夹下, 然后打开AndroidManifest.xml这个配置清单文件找 到application标签里的这句android:icon= ...