题目链接  Envy

题意  给出一个连通的无向图和若干询问。每个询问为一个边集。求是否存在某一棵原图的最小生成树包含了这个边集。

考虑$kruskal$的整个过程,

当前面$k$条边已经完成操作的时候(就是前$k$小的边已经进行并查集缩点,此时部分点已经形成了若干个连通块)

这个时候突然冒出来一些权值相同并且这个权值大于前$k$条边最大权值的边,问这些边是否能同时被某一棵最小生成树包含。

那我们依次检查这突然冒出来的几条边,在原来的这个并查集的基础上,继续进行缩点操作。

如果这些边在处理的时候没有遇到某条边的两个点在连边之前已经连通的情况,那么这些边能同时被某一棵最小生成树包含。

反之亦然。

对于这道题我们要做的就是把所有询问离线,把每条询问边塞到对应的权值里面。

当我现在要检查权值为$x$的某些同一个询问里的边的时候,首先要保证那些权值小于$x$的边都已经进行了并查集缩点。

然后把这些权值为$x$的某些同一个询问里的边想象成刚刚说的“突然冒出来的几条边”,检查就可以了。

如果不行的话这个询问的$id$的答案就是$NO$了。

因为同一个权值里面可能会有(其实是一般都有)询问id不同的边,那么处理完某一批边之后我们要对询问的时候改动的并查集撤销。

开个栈记录一下即可。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define MP make_pair
  8. #define fi first
  9. #define se second
  10.  
  11. typedef pair <int, int> PII;
  12.  
  13. const int N = 5e5 + 10;
  14.  
  15. struct node{
  16. int x, y, z;
  17. void scan(){ scanf("%d%d%d", &x, &y, &z);}
  18. } e[N];
  19.  
  20. struct query{
  21. int x, y, id;
  22. friend bool operator < (const query &a, const query &b){
  23. return a.id < b.id;
  24. }
  25. };
  26.  
  27. int father[N], ret[N], n, m, qu, now, opnum;
  28. stack <PII> s;
  29. vector <query> v[N];
  30. vector <PII> g[N];
  31.  
  32. int getfather(int x){
  33. if (father[x]){
  34. s.push(MP(x, father[x]));
  35. father[x] = getfather(father[x]);
  36. return father[x];
  37. }
  38.  
  39. else return x;
  40. }
  41.  
  42. int gf(int x){ return father[x] ? father[x] = gf(father[x]) : x;}
  43.  
  44. void work(int x, int y){
  45. int fx = gf(x), fy = gf(y);
  46. if (fx ^ fy) father[fx] = fy;
  47. }
  48.  
  49. void solve(int cnt, int x, int y){
  50. while (!s.empty()) s.pop();
  51. rep(i, x, y){
  52. int fx = getfather(v[cnt][i].x), fy = getfather(v[cnt][i].y);
  53. if (fx == fy) ret[v[cnt][i].id] = 1;
  54. else{
  55. s.push(MP(fx, father[fx]));
  56. father[fx] = fy;
  57. }
  58. }
  59.  
  60. while (!s.empty()){
  61. father[s.top().fi] = s.top().se;
  62. s.pop();
  63. }
  64. }
  65.  
  66. int main(){
  67.  
  68. scanf("%d%d", &n, &m);
  69. rep(i, 1, m){
  70. e[i].scan();
  71. g[e[i].z].push_back(MP(e[i].x, e[i].y));
  72. }
  73.  
  74. scanf("%d", &qu);
  75. rep(i, 1, qu){
  76. int opnum;
  77. scanf("%d", &opnum);
  78. rep(j, 1, opnum){
  79. int x;
  80. scanf("%d", &x);
  81. v[e[x].z].push_back({e[x].x, e[x].y, i});
  82. }
  83. }
  84.  
  85. rep(i, 1, 5e5) sort(v[i].begin(), v[i].end());
  86. rep(i, 1, 5e5){
  87. for (auto u : g[i - 1]) work(u.fi, u.se);
  88. int sz = v[i].size();
  89. if (sz == 0) continue;
  90. int now = 0;
  91. while (now < sz){
  92. int j = now;
  93. while (j + 1 < sz && v[i][j + 1].id == v[i][j].id) ++j;
  94. solve(i, now, j);
  95. now = j + 1;
  96. }
  97. }
  98.  
  99. rep(i, 1, qu) puts(ret[i] ? "NO" : "YES");
  100. return 0;
  101. }

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. 拓扑排序+不是字典序的优先级排列(POJ3687+HDU4857)

    一.前言 在过去的一周里结束了CCSP的比赛,其中有一道题卡了我9个小时,各种调错都没法完整的调处来这题,于是痛下决心开始补题,这个是计划的一部分.事实上,基于错误的理解我写了若干发拓扑排序+字典序的 ...

  2. 成为Java高手的25个学习要点

    成为Java高手的25个学习要点 想成为Java大牛吗?不妨来学习这25个要点. 1. 你需要精通面向对象分析与设计(OOA/OOD).涉及模式(GOF,J2EEDP)以及综合模式.你应该了解UML, ...

  3. Marketing learning-1

    Today we start to learn something about marketing together.Sometimes i just propose a question,and i ...

  4. IOS开发学习笔记005-数组

    数组 数组故名思议就是一组数据的集合. int a[10];//可以存储10个整数 char  c[8];//可以存储8个字符‘ 一般格式:数组类型 数组名[元素个数]: 数组元素的访问:下标,a[2 ...

  5. hibernate 出错 集合

    Lazy="false"反而出错 错误信息: “System.Configuration.ConfigurationErrorsException”类型的异常在 Spring.Co ...

  6. vmware克隆centos修改linux mac地址

    故障背景:  在vmware workstation中了完全克隆了一个已经存在的centos的虚拟机,启动之后发现网卡没有启动.于是重启一下network服务,发现提示错误信息“Device eth0 ...

  7. CSU-2172 买一送一

    CSU-2172 买一送一 Description ICPCCamp 有 n 个商店,用 1, 2, -, n 编号.对于任意 i > 1,有从商店 \(p_i\) 到 i 的单向道路. 同时, ...

  8. Leetcode 647.回文子串

    回文子串 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串. 示例 1: 输入: "abc&qu ...

  9. Leetcode 639.解码方法2

    解码方法2 一条包含字母 A-Z 的消息通过以下的方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 除了上述的条件以外,现在加密字符串可以包含字符 ' ...

  10. poj3009 Curling 2.0 (DFS按直线算步骤)

    Curling 2.0 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14563   Accepted: 6080 Desc ...