题目链接  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 + 并查集的撤销)的更多相关文章

  1. Codeforces Gym 100463E Spies 并查集

    Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...

  2. Codeforces 859E Desk Disorder 并查集找环,乘法原理

    题目链接:http://codeforces.com/contest/859/problem/E 题意:有N个人.2N个座位.现在告诉你这N个人它们现在的座位.以及它们想去的座位.每个人可以去它们想去 ...

  3. Codeforces - 828C String Reconstruction —— 并查集find()函数

    题目链接:http://codeforces.com/contest/828/problem/C C. String Reconstruction time limit per test 2 seco ...

  4. Codeforces 571D - Campus(并查集+线段树+DFS 序,hot tea)

    Codeforces 题目传送门 & 洛谷题目传送门 看到集合的合并,可以本能地想到并查集. 不过这题的操作与传统意义上的并查集不太一样,传统意义上的并查集一般是用来判断连通性的,而此题还需支 ...

  5. CodeForces 455C Civilization (并查集+树的直径)

    Civilization 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/B Description Andrew plays a ...

  6. Codeforces 650C Table Compression (并查集)

    题意:M×N的矩阵 让你保持每行每列的大小对应关系不变,将矩阵重写,重写后的最大值最小. 思路:离散化思想+并查集,详见代码 好题! #include <iostream> #includ ...

  7. Codeforces 468B Two Sets 并查集

    题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合. 写了几个版本号,一直WA在第8组数据...最后參考下ans,写了并查集过了 学到:1.注意离散的 ...

  8. CodeForces - 893C Rumor【并查集】

    <题目链接> 题目大意: 有n个人,其中有m对朋友,现在你有一个秘密你想告诉所有人,第i个人愿意出价a[i]买你的秘密,获得秘密的人会免费告诉它的所有朋友(他朋友的朋友也会免费知道),现在 ...

  9. CodeForces 566D Restructuring Company (并查集+链表)

    题意:给定 3 种操作, 第一种 1 u v 把 u 和 v 合并 第二种 2 l r 把 l - r 这一段区间合并 第三种 3 u v 判断 u 和 v 是不是在同一集合中. 析:很容易知道是用并 ...

随机推荐

  1. UVA_1025 a Spy in the Metro 有向无环图的动态规划问题

    应当认为,有向无环图上的动态规划问题是动态规划的基本模型之一,对于某个模型,如果可以转换为某一有向无环图的最长.最短路径问题,则可以套用动态规划若干方法解决. 原题参见刘汝佳紫薯267页. 在这个题目 ...

  2. Nodejs-文件流

    1.什么是流? 流是程序输入输出的一个连续的字节序列. 有文件流,网络流,设备(例如鼠标,键盘,磁盘,调制解调器和打印机)的输入输出都是用流来处理的. 任何数据的最根本表现形式都是二进制. 读取文件 ...

  3. IOS笔记051-手势使用

    UIGestureRecognizer 利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势 UIGestureRecognizer是一个抽象类,定义了所有手势 ...

  4. gcc学习记录

    -Wall: 使输出中包含警告信息,提示一些可以避免的错误.如果没有错误,则不会输出信息. -o:后面加上可执行文件的名字.如果不加-o选项,会默认生成a.out可执行文件.举例:gcc -Wall ...

  5. centos 7 配置ip

    1.动态获取ip(前提是你的路由器已经开启了DHCP) 修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens32    (最后一个为网卡名称) 动态 ...

  6. TOJ 3750: 二分查找

    3750: 二分查找   Time Limit(Common/Java):3000MS/9000MS     Memory Limit:65536KByteTotal Submit: 1925     ...

  7. ftp下出现“当前的安全设置不允许从该位置下载文件”提示

    在资源管理器中使用ftp协议下载文件时,提示“当前的安全设置不允许从该位置下载文件”,下载失败. 解决方法: 1.在自己的电脑上打开Internet选项

  8. spring 解决中文乱码问题

    spring 解决中文乱码问题 使用spring的前提下在web.xml中配置 <filter> <filter-name>encodingFilter</filter- ...

  9. A.Equals(B)和A==B的区别

    Equals 和 == 都是用于比较. 如果a和b都是值类型,则a.Equals(b) 和 a == b 结果相同,但是在引用类型是它们的行为是不同的: string a = new string(n ...

  10. Java接口对Hadoop集群的操作

    Java接口对Hadoop集群的操作 首先要有一个配置好的Hadoop集群 这里是我在SSM框架搭建的项目的测试类中实现的 一.windows下配置环境变量 下载文件并解压到C盘或者其他目录. 链接: ...