题意:有一张 $n$ 个点$ m $条边的连通图。有$Q$ 次询问。每次询问给出 $k[i]$ 条边,问这些边能否同时出现在一棵最小生成树上。$n,m,Q,\sum k\le 500000$。


这题利用到了最小生成树的一个性质,可以结合我记的最小生成树笔记。在加入所有权值前$i-1$大的边后,目前的权值第$i$大的一些边不管怎么加,连通性都是一样的,也就是连通块内的点集都是一样的,只不过有一些剩下的边或者连接两个块内点的边不合法罢了。于是可以在kruskal的时候先处理出对于每条边,他连接的两个连通块是什么(以当时的角度记录块上并查集祖先)。然后处理询问的时候,排序后对于权值相同的边,用并查集判断他们连接的连通块是否有环,即合不合法即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<queue>
  7. #define dbg(x) cerr << #x << " = " << x <<endl
  8. #define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
  9. using namespace std;
  10. typedef long long ll;
  11. typedef double db;
  12. typedef pair<int,int> pii;
  13. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  14. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  15. template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
  16. template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
  17. template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
  18. template<typename T>inline T read(T&x){
  19. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  20. while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
  21. }
  22. const int N=5e5+;
  23. int n,m,q,k;
  24. struct thxorz{
  25. int u,v,w,id;
  26. inline bool operator <(const thxorz&A){return w<A.w;}
  27. }e[N];
  28. struct stothx{int fx,fy,w;}g[N];
  29. int anc[N];
  30. int find_anc(int x){return x==anc[x]?x:anc[x]=find_anc(anc[x]);}
  31.  
  32. inline void Kruskal(){
  33. sort(e+,e+m+);
  34. for(register int i=;i<=n;++i)anc[i]=i;
  35. for(register int i=,st=;i<=m;++i)if(e[i].w^e[i+].w){
  36. for(register int j=st;j<=i;++j)
  37. g[e[j].id].fx=find_anc(e[j].u),g[e[j].id].fy=find_anc(e[j].v);//dbg(e[j].id),dbg2(g[e[j].id].fx,g[e[j].id].fy);
  38. for(register int j=st;j<=i;++j)
  39. anc[find_anc(g[e[j].id].fx)]=find_anc(g[e[j].id].fy);
  40. st=i+;
  41. }
  42. }
  43. int a[N],vis[N],cnt;
  44. inline bool cmp(int a,int b){return g[a].w<g[b].w;}
  45. inline void Query(){
  46. read(k);for(register int i=;i<=k;++i)read(a[i]);a[k+]=;
  47. sort(a+,a+k+,cmp);
  48. for(register int i=,st=;i<=k;++i)if(g[a[i]].w^g[a[i+]].w){
  49. for(register int j=st;j<=i;++j){//dbg(a[j]);
  50. int fx=find_anc(g[a[j]].fx),fy=find_anc(g[a[j]].fy);//dbg2(fx,fy);
  51. if(fx^fy)anc[fx]=fy,vis[++cnt]=fx;
  52. else{while(cnt)anc[vis[cnt]]=vis[cnt],--cnt;puts("NO");return;}
  53. }
  54. st=i+;
  55. while(cnt)anc[vis[cnt]]=vis[cnt],--cnt;
  56. }
  57. puts("YES");
  58. }
  59.  
  60. int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
  61. read(n),read(m);
  62. for(register int i=;i<=m;++i)read(e[i].u),read(e[i].v),g[i].w=read(e[i].w),e[i].id=i;
  63. Kruskal();
  64. for(register int i=;i<=n;++i)anc[i]=i;
  65. read(q);while(q--)Query();
  66. return ;
  67. }

总结:要理解kruskal本质和其性质,从而进行改造,注意连通块性质。

CF892E Envy[最小生成树]的更多相关文章

  1. CF891C Envy 最小生成树/虚树

    正解:最小生成树/虚树 解题报告: 传送门! sd如我就只想到了最暴力的想法,一点儿优化都麻油想到,,,真的菜到爆炸了QAQ 然后就分别港下两个正解QAQ 法一,最小生成树 这个主要是要想到关于最小生 ...

  2. 【CF891C】Envy(最小生成树)

    [CF891C]Envy(最小生成树) 题面 Codeforces 洛谷 题解 考虑\(MST\)的构建过程,对于所有权值相同的边一起考虑. 显然最终他们连出来的结果是固定的. 把连边改为把联通块联通 ...

  3. 【CF891C】Envy 离线+最小生成树

    [CF891C]Envy 题意:给你一个图,边有边权,每次询问给你一堆边,问你是否存在一个原图的最小生成树包含给出的所有边.n,m,q<=100000 题解:思路很好的题. 首先有一个非常重要的 ...

  4. CodeForces - 891C: Envy(可撤销的并查集&最小生成树)

    For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph of G that con ...

  5. CF891C Envy【最小生成树】

    题目链接 我们知道,根据Kruskal的贪心,对于最小生成树,每一种权值的边数是一样的,而且如果将\(\leq x\)的边做最小生成树,合法方案的联通性是一样的.所以我们可以对于所有边分开考虑. 对于 ...

  6. Codeforces 891C Envy

    Envy 感觉这种最小生成树上的啥题都差不多的解法.. #include<bits/stdc++.h> #define LL long long #define fi first #def ...

  7. Codeforces 891C Envy(MST + 并查集的撤销)

    题目链接  Envy 题意  给出一个连通的无向图和若干询问.每个询问为一个边集.求是否存在某一棵原图的最小生成树包含了这个边集. 考虑$kruskal$的整个过程, 当前面$k$条边已经完成操作的时 ...

  8. 代码的坏味道(18)——依恋情结(Feature Envy)

    坏味道--依恋情结(Feature Envy) 特征 一个函数访问其它对象的数据比访问自己的数据更多. 问题原因 这种气味可能发生在字段移动到数据类之后.如果是这种情况,你可能想将数据类的操作移动到这 ...

  9. 最小生成树(Kruskal算法-边集数组)

    以此图为例: package com.datastruct; import java.util.Scanner; public class TestKruskal { private static c ...

随机推荐

  1. 零零散散的python笔记 2

    python2和python3的兼容性方面 工具 2to3 python3中自带的工具,可以检查python2升级到python3的diff: 2to3 x.py 2to3 -w x.py     # ...

  2. python程序开子进程打包成exe文件运行炸内存原因剖析

    首先给出伪代码 from multiprocessing import Process def task(): print("hahaha") pass if __name__ = ...

  3. PYTHON 100days学习笔记006:函数和模块的使用

    目录 Day006:函数和模块的使用 1.函数的作用 2.定义函数 2.1 语法 2.2 实例 2.3 函数的调用 4.函数的参数 4.1 必须参数 4.2 关键字参数 4.3 默认参数 4.4 不定 ...

  4. vultr 更换服务器

    今天打算去p站看看电影 结果发现自己的vps被封了......记录一下换服务器的过程 首先去 https://www.17ce.com/ ping一下,发现只有国外的服务器能ping通 果然是被封了. ...

  5. SQL2000中文版打不上SP4提示用户验证没有通过

    https://jingyan.baidu.com/article/7f41ececf24841593d095cd8.html 解决方法: 在安装SQL Server SP4,有时候会出现:无论用wi ...

  6. oracle数据库基于(streams流复制)的双机热备配置手册

    ------------------------------------------------------------------------------- 主数据库: 操作系统:windows 2 ...

  7. Android Application的Gradle说明

    //引入插件 apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion &quo ...

  8. winform 中如何获取debug目录的路径

    项目中需要在debug启动目录创建文件夹,所以先获取debug路径: var debugPath = System.AppDomain.CurrentDomain.BaseDirectory;

  9. T100错误信息提示方式

    例如: IF g_browser_cnt = THEN INITIALIZE g_errparam TO NULL LET g_errparam.extend = "" LET g ...

  10. 【其他】BootCDN

    BootCDN 稳定.快速.免费的前端开源项目 CDN 加速服务 是 Bootstrap 中文网支持并维护的前端开源项目免费 CDN 服务,致力于为 Bootstrap.jQuery.Angular. ...