传送门:here

简述题意:                                                                                           

给定一张$ n$个点,$ m$条边$ (2<=n,m<=5*10^5)$的无向连通图

有$ k(1<=k<=5*10^5)$次询问

每次询问一个边集$ S(\sum\limits_{i=1}^k|S_i|<=5*10^5)$,判断这些边能否共存于原图的某棵最小生成树上

并查集撤销上一次操作:                                                                      

不能像普通并查集一样路径压缩,因此只能按址合并

每次把size较小的接到size较大的下面

同时开个栈记录被接上去的点的标号

撤销上一次操作的时候直接把栈顶的标号的father重标成自己同时减小原father的size值即可

题解:                                                                                                 

先简化题意:假设每次询问的边集大小均为1

思考克鲁斯卡尔的原理

首先对所有边按边权从小到大排序

克鲁斯卡尔告诉我们一条当前可插入的边权最小的边,插入一定不会不优

因而一条边权为x的边可以在最小生成树内当且仅当把所有权值严格小于x的边插入生成树后加入这条边依然不会形成环

也就是说边权不同的边相互独立,从小到大贪心即可

因此我们把询问离线排序,从小到大判断每次询问对应的边可否插入,可插入则该次询问为YES且插入,否则该次询问一定为NO

如果有两条边边权相同怎么办?

直接检验不一定正确,因为前一条边不一定必选,而之前程序已经将其插入

因此需要撤销上一次并查集的合并操作,然后再检验下一条边

回到原题

我们知道边集大小不一定为1

依然按边权排序,在每条询问边标记询问标号

由于之前提到不同边权相互独立,因此只要某组询问的每一种边权对应的边可以全选,最终也一定可行

反之只要一个询问中有一条边不合法则不可行

因此像上面一样排序后从小到大扫即可

注意同一个询问的相同边权的边检验必须一起做,全部做完之后再一起撤销

因为在同一个询问里同一种边权是不独立的,必须全部插入后依然不形成环才可行

code:                                                                                                 

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #define rt register int
  7. #define l putchar('\n')
  8. #define ll long long
  9. #define M 1000010
  10. using namespace std;
  11. inline ll read()
  12. {
  13. register ll x = ; char zf = ; char ch;
  14. while (ch != '-' && !isdigit(ch)) ch = getchar();
  15. if (ch == '-') zf = -, ch = getchar();
  16. while (isdigit(ch)) x = x * + ch - '', ch = getchar(); return x * zf;
  17. }
  18. int i,j,k,m,n,x,y,z,cnt,la[M],fa[M],size[M],top,g=;
  19. int ask(int x)
  20. {
  21. while(fa[x]!=x)x=fa[x];
  22. return x;
  23. }
  24. void merge(int x,int y)
  25. {
  26. if(x==y)return;
  27. if(size[x]>size[y])swap(x,y);la[++top]=x;
  28. fa[x]=y;size[y]+=size[x];
  29. }
  30. void undo()
  31. {
  32. int La=la[top];
  33. size[fa[La]]-=size[La];
  34. fa[La]=La;top--;
  35. }
  36. struct ed
  37. {
  38. int x,y,z;
  39. inline bool operator <(const ed s)const
  40. {
  41. return z<s.z;
  42. }
  43. }q[M];
  44.  
  45. struct query
  46. {
  47. int id,x,y,val;
  48. inline bool operator <(const query s)const
  49. {
  50. if(val==s.val)return id<s.id;
  51. return val<s.val;
  52. }
  53. }A[M];
  54. int ans[M];
  55. int main()
  56. {
  57. n=read();m=read();
  58. for(rt i=;i<=n;i++)size[i]=,fa[i]=i;
  59. for(rt i=;i<=m;i++)
  60. {
  61. x=read();y=read();z=read();
  62. q[i]={x,y,z};
  63. }
  64.  
  65. k=read();
  66. for(rt e=;e<=k;e++)
  67. {
  68. z=read();ans[e]=;
  69. for(rt i=;i<=z;i++)
  70. {
  71. x=read();
  72. A[++cnt]={e,q[x].x,q[x].y,q[x].z};
  73. }
  74. }
  75. sort(q+,q+m+);
  76. sort(A+,A+cnt+);
  77. int qd=;
  78. for(rt i=;i<=cnt;)
  79. {
  80. while(q[qd].z<A[i].val)
  81. merge(ask(q[qd].x),ask(q[qd].y)),qd++;
  82.  
  83. top=;
  84. do
  85. {
  86.  
  87. int p1=ask(A[i].x),q1=ask(A[i].y);
  88. if(p1==q1)ans[A[i].id]=;
  89. merge(p1,q1);
  90. i++;
  91. }while(A[i].val==A[i-].val&&A[i].id==A[i-].id);
  92. while(top)undo();
  93. }
  94. for(rt i=;i<=k;i++)puts(ans[i]?"YES":"NO");
  95. return ;
  96. }

Codeforces891C(892E)的更多相关文章

  1. Codeforces891C. Envy

    $n \leq 5e5$,$m \leq 5e5$的无向边权图,$q \leq 5e5$个询问,每次问一系列边是否能同时存在于某棵最小生成树上. 一条边在最小生成树上,当比他小的边都加入后,加入他会使 ...

  2. codeforces 892E(离散化+可撤销并查集)

    题意 给出一个n个点m条边的无向联通图(n,m<=5e5),有q(q<=5e5)个询问 每个询问询问一个边集{Ei},回答这些边能否在同一个最小生成树中 分析 要知道一个性质,就是权值不同 ...

  3. Codeforces 892E Envy

    问题描述 小Q正在玩一个叠塔的游戏,游戏的目标是叠出尽可能高的塔.在游戏中,一共有n张矩形卡片,其中第i张卡片的 长度为a_i,宽度为b_i.小Q需要把所有卡片按一定顺序叠成一座塔,要求对于任意一个矩 ...

  4. REORG TABLESPACE on z/os

    这个困扰了我两天的问题终于解决了,在运行这个job时:总是提示 A REQUIRED DD CARD OR TEMPLATE IS MISSING NAME=SYSDISC A REQUIRED DD ...

  5. Neutron命令测试5

    jolin@jolin:/$ route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface ...

  6. Neutron命令测试4

    jolin@jolin:~$ route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface ...

随机推荐

  1. 关于json_encode转数组为json对象时里有数组格式数据的问题

    前言:这次是给一款小程序提供接口时发现的 别的不多说,下面直接看出现问题的json数据 可以看到,这是一个大的json对象,是由多维数组组成,一般api接口提供的也是这种格式. 但是仔细看红框中的内容 ...

  2. Redis和memcached区别须知

    1.支持的数据类型不同(memcached只支持简单的key-value的数据类型,Redis支持5种数据类型(1.string,2.list,3.set,4.zset,5.hash)) 2.redi ...

  3. 斯坦福大学公开课机器学习: advice for applying machine learning | deciding what to try next(revisited)(针对高偏差、高方差问题的解决方法以及隐藏层数的选择)

    针对高偏差.高方差问题的解决方法: 1.解决高方差问题的方案:增大训练样本量.缩小特征量.增大lambda值 2.解决高偏差问题的方案:增大特征量.增加多项式特征(比如x1*x2,x1的平方等等).减 ...

  4. java统计指定目录中文件的个数和总的大小

    转: 统计指定目录中文件的个数和总的大小 package file; import java.io.File; import java.util.ArrayList; public class Fil ...

  5. RabbitMQ入门-竞争消费者模式

    上一篇讲了个 哈喽World,现在来看看如果存在多个消费者的情况. 生产者: package com.example.demo; import com.rabbitmq.client.Channel; ...

  6. C#Windows服务程序安装常见问题解决方法

    C#Windows服务程序安装是如何的呢?让我们开始吧: C#Windows服务程序安装1. 在服务程序的是设计窗体中,点击右键“添加安装程序”,添加服务安装程序.否则,安装时会出现如下 错误: 正在 ...

  7. 多元线性回归(Multivariate Linear Regression)简单应用

    警告:本文为小白入门学习笔记 数据集: http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=DeepLearnin ...

  8. (最小生成树 Prim) nyoj1403-沟通无限校园网

    题目描述: 校园网是为学校师生提供资源共享.信息交流和协同工作的计算机网络.校园网是一个宽带.具有交互功能和专业性很强的局域网络.如果一所学校包括多个学院及部门,也可以形成多个局域网络,并通过有线或无 ...

  9. Java基础方法整理

    方法 9.1方法概述 方法就是用来完成解决某件事情或实现某个功能的办法 可以通过在程序代码中引用方法名称和所需的参数,实现在该程序中执行(或称调用)该方法.方法,一般都有一个返回值,用来作为事情的处理 ...

  10. kafka与zookeeper

    kafka简介 kafka (官网地址:http://kafka.apache.org)是一款分布式消息发布和订阅的系统,具有高性能和高吞吐率. 下载地址:http://kafka.apache.or ...