题目链接  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. java中如何判断一个字符串是否包含另外一个字符串的方法

    indexOf(String s)的使用,如果包含,返回的值是包含该子字符串在父类字符串中起始位置: 如果不包含必定全部返回值为-1 package my_automation; public cla ...

  2. springboot(七):springboot+mybatis多数据源最简解决方案

    说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解 ...

  3. java包、类、方法、属性、常量命名规则

    必须用英文,不要用汉语拼音 1:包(package):用于将完成不同功能的类分门别类,放在不同的目录(包)下,包的命名规则:将公司域名反转作为包名.比如www.sohu.com 对于包名:每个字母都需 ...

  4. 精通CSS高级Web标准解决方案(5、对列表应用样式和创建导航条)

    5.1基本样式列表 去掉列表的默认样式: ul{ margin:; padding:; list-style-type:none; } 添加定制的符号,在列表左边添加填充,为符号留出空间,然后将符号图 ...

  5. hadoop配置文件: hdfs-site.xml, mapred-site.xml

    dfs.name.dir Determines where on the local filesystem the DFS name node should store the name table( ...

  6. jquery的html、text、val的用法

    .html()用为读取和修改元素的HTML标签 .text()用来读取或修改元素的纯文本内容 .val()用来读取或修改表单元素的value值. 这三个方法功能上的对比 .html(),.text() ...

  7. Spring4.0实战 rest相关

    package com.paic.pay.merchant.web; import com.paic.pay.merchant.entity.MerchantUser; import com.paic ...

  8. 【bzoj3544】[ONTAK2010]Creative Accounting 前缀和+STL-set

    题目描述 给定一个长度为N的数组a和M,求一个区间[l,r],使得$(\sum\limits_{i=l}^{r}{a_i})\ mod\ M$的值最大,求出这个值,注意这里的mod是数学上的mod(即 ...

  9. ZigBee学习三 UART通信

    ZigBee学习三 UART通信 在使用串口时,只需掌握ZigBee协议栈提供的串口操作相关的三个函数即可. uint8 HalUARTOpen(uint8 port,halUARTCfg_t *co ...

  10. python 小爬虫

    import reimport urllibdef getHtml(url): page=urllib.urlopen(url); html=page.read() return htmldef ge ...