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 是不是在同一集合中. 析:很容易知道是用并 ...
随机推荐
- mysql-update时where条件无索引锁全表
1 5.3日数据处理需求 UPDATE md_meter set warranty_end_date = DATE_ADD(warranty_begin_date,INTERVAL 10 ...
- SQLAlchemy Script
SQLAlchemy: 1.由于sqlalchemy中没有提供choice方法,所以借助SQLAlchemy-Utils组件提供的choice方法 from sqlalchemy_utils impo ...
- 3、CSS基础 part-1
1.给body设置颜色 <html> <body text="red"> <p> hello world</p> <p> ...
- 【POJ 3764】The Xor-longest Path
题目 给定一个\(n\)个点的带权无根树,求树上异或和最大的一条路径. \(n\le 10^5\) 分析 一个简单的例子 相信大家都做过这题: 给定一个\(n\)个点的带权无根树,有\(m\)个询问, ...
- 查看2个Python字典的相同以及不同之处
a = { "x":1, "y":2, "z":3 } b = { "x":1, "w":11, & ...
- mvc-自定义视图引擎
//自定义视图引擎的实质是把数据模型(moudle)和模板(View)转换成html页面,输出到客户端public class MyView:IView { string _viewPath; pub ...
- Swift全栈开发
前段时间学习了一下Swift web framework-Vapor, 类似于PHP Laravel的web框架. Apple也成立了Server APIs Project, Server-side ...
- TOJ5272: 逆矩阵
5272: 逆矩阵 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 11 ...
- algorithm 头文件
非修改性序列操作(12个) 循环 对序列中的每个元素执行某操作 for_each() 查找 在序列中找出某个值的第一次出现的位置 find() 在序列中找出符合某谓词的第一个元素 find_if() ...
- SOCK5代理服务器
SOCK5代理服务器 简单介绍下比较好用的代理服务器,在部署过程中在内外网访问,需要切网比较麻烦,所以可以在互联网区部署sock5代理,通过配置代理切换服务器, 比较方便配置,节省时间. 官网: ht ...