Codeforces 891C Envy(MST + 并查集的撤销)
题目链接 Envy
题意 给出一个连通的无向图和若干询问。每个询问为一个边集。求是否存在某一棵原图的最小生成树包含了这个边集。
考虑$kruskal$的整个过程,
当前面$k$条边已经完成操作的时候(就是前$k$小的边已经进行并查集缩点,此时部分点已经形成了若干个连通块)
这个时候突然冒出来一些权值相同并且这个权值大于前$k$条边最大权值的边,问这些边是否能同时被某一棵最小生成树包含。
那我们依次检查这突然冒出来的几条边,在原来的这个并查集的基础上,继续进行缩点操作。
如果这些边在处理的时候没有遇到某条边的两个点在连边之前已经连通的情况,那么这些边能同时被某一棵最小生成树包含。
反之亦然。
对于这道题我们要做的就是把所有询问离线,把每条询问边塞到对应的权值里面。
当我现在要检查权值为$x$的某些同一个询问里的边的时候,首先要保证那些权值小于$x$的边都已经进行了并查集缩点。
然后把这些权值为$x$的某些同一个询问里的边想象成刚刚说的“突然冒出来的几条边”,检查就可以了。
如果不行的话这个询问的$id$的答案就是$NO$了。
因为同一个权值里面可能会有(其实是一般都有)询问id不同的边,那么处理完某一批边之后我们要对询问的时候改动的并查集撤销。
开个栈记录一下即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef pair <int, int> PII; const int N = 5e5 + 10; struct node{
int x, y, z;
void scan(){ scanf("%d%d%d", &x, &y, &z);}
} e[N]; struct query{
int x, y, id;
friend bool operator < (const query &a, const query &b){
return a.id < b.id;
}
}; int father[N], ret[N], n, m, qu, now, opnum;
stack <PII> s;
vector <query> v[N];
vector <PII> g[N]; int getfather(int x){
if (father[x]){
s.push(MP(x, father[x]));
father[x] = getfather(father[x]);
return father[x];
} else return x;
} int gf(int x){ return father[x] ? father[x] = gf(father[x]) : x;} void work(int x, int y){
int fx = gf(x), fy = gf(y);
if (fx ^ fy) father[fx] = fy;
} void solve(int cnt, int x, int y){
while (!s.empty()) s.pop();
rep(i, x, y){
int fx = getfather(v[cnt][i].x), fy = getfather(v[cnt][i].y);
if (fx == fy) ret[v[cnt][i].id] = 1;
else{
s.push(MP(fx, father[fx]));
father[fx] = fy;
}
} while (!s.empty()){
father[s.top().fi] = s.top().se;
s.pop();
}
} int main(){ scanf("%d%d", &n, &m);
rep(i, 1, m){
e[i].scan();
g[e[i].z].push_back(MP(e[i].x, e[i].y));
} scanf("%d", &qu);
rep(i, 1, qu){
int opnum;
scanf("%d", &opnum);
rep(j, 1, opnum){
int x;
scanf("%d", &x);
v[e[x].z].push_back({e[x].x, e[x].y, i});
}
} rep(i, 1, 5e5) sort(v[i].begin(), v[i].end());
rep(i, 1, 5e5){
for (auto u : g[i - 1]) work(u.fi, u.se);
int sz = v[i].size();
if (sz == 0) continue;
int now = 0;
while (now < sz){
int j = now;
while (j + 1 < sz && v[i][j + 1].id == v[i][j].id) ++j;
solve(i, now, j);
now = j + 1;
}
} rep(i, 1, qu) puts(ret[i] ? "NO" : "YES");
return 0;
}
Codeforces 891C Envy(MST + 并查集的撤销)的更多相关文章
- Codeforces Gym 100463E Spies 并查集
Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...
- Codeforces 859E Desk Disorder 并查集找环,乘法原理
题目链接:http://codeforces.com/contest/859/problem/E 题意:有N个人.2N个座位.现在告诉你这N个人它们现在的座位.以及它们想去的座位.每个人可以去它们想去 ...
- Codeforces - 828C String Reconstruction —— 并查集find()函数
题目链接:http://codeforces.com/contest/828/problem/C C. String Reconstruction time limit per test 2 seco ...
- Codeforces 571D - Campus(并查集+线段树+DFS 序,hot tea)
Codeforces 题目传送门 & 洛谷题目传送门 看到集合的合并,可以本能地想到并查集. 不过这题的操作与传统意义上的并查集不太一样,传统意义上的并查集一般是用来判断连通性的,而此题还需支 ...
- CodeForces 455C Civilization (并查集+树的直径)
Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...
- Codeforces 650C Table Compression (并查集)
题意:M×N的矩阵 让你保持每行每列的大小对应关系不变,将矩阵重写,重写后的最大值最小. 思路:离散化思想+并查集,详见代码 好题! #include <iostream> #includ ...
- Codeforces 468B Two Sets 并查集
题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合. 写了几个版本号,一直WA在第8组数据...最后參考下ans,写了并查集过了 学到:1.注意离散的 ...
- CodeForces - 893C Rumor【并查集】
<题目链接> 题目大意: 有n个人,其中有m对朋友,现在你有一个秘密你想告诉所有人,第i个人愿意出价a[i]买你的秘密,获得秘密的人会免费告诉它的所有朋友(他朋友的朋友也会免费知道),现在 ...
- CodeForces 566D Restructuring Company (并查集+链表)
题意:给定 3 种操作, 第一种 1 u v 把 u 和 v 合并 第二种 2 l r 把 l - r 这一段区间合并 第三种 3 u v 判断 u 和 v 是不是在同一集合中. 析:很容易知道是用并 ...
随机推荐
- [BZOJ1588]营业额统计(Splay)
Description 题意:给定 n个数,每给定一个数,在之前的数里找一个与当前数相差最小的数,求相差之和(第一个数为它本身) 如:5 1 2 5 4 6 Ans=5+|1-5|+|2-1|+|5- ...
- 51nod_1154 回文串的划分
说实话..最开始看这题感觉一定好难...好高大上...我的马拉车还不熟....这种..但是本着做不出来也要至少看看的心态,吧个题看完了..然后简单的想了想,好像是个挺直观的动态规划,因为看到数据几乎就 ...
- javaScripct入门教程
1.JavaScript环境安装 JavaScript是一个轻量级的编程语言,安装自然很简单. a.打开你的电脑,找到一个Web浏览器,再找一个文本编辑器(比如记事本) b.没有了... 2.Java ...
- json对象数据列数
// var len = data.length(); // alert(data.Rows.length); var colCount = (function count(){//一条记录中有几个键 ...
- gulp基本入门
gulp用于自动化和提高工作流,类似于grunt.gulp适用于nodejs平台. gulp基础: gulp两个主要的功能是读取想要处理的文件,把处理好的文件放到指定的地方gulp.src()找出 ...
- BMP图片的加载方式:资源 VS 文件
在程序中加载位图有很多方法,各有各的好处.这里简单说一下在资源里和文件里加载的区别. 第一.在资源里加载位图 这种方法就是在工程里的“资源视图”-->“添加资源”-->"Bitm ...
- pc和移动端获取滚动条的位置
移动端获取滚动条:document.body.scrollTop pc端获取滚动条:document.documentElement.scrollTop
- VMware Fusion Pro安装Ubuntu 18.04.1
- day02_02.能被3整除的个位数为6的数
第2题 能被3整除的个位数为6的数 难度增加一点点,再接再厉 注意: 把一些限制条件,用PHP编程的语言来执行 题目:输出100以内(不含100)能被3整除且个位数为6的所有整数 <?php f ...
- Postgresql 查看建表语句 命令
pg_dump -U username databasename -W -s -t tablename -s, --schema-only 只转储模式, 不包括数据 -t, --table=TABLE ...