题目链接:点击查看

题目大意:给出一张由 n 个点 m 条边组成的连通图,有 q 次询问,每次询问给出一个边集,需要判断这些边是否可以同时出现在最小生成树上

题目分析:需要用到的一个性质是,对于同一个询问来说,不同权值的选择是相互独立的,但是相同权值之间会相互影响,所以我们可以对每个询问的每条边单独拿出来讨论

在进行正常的最小生成树的操作时,对于每次操作的当前边 i ,需要处理所有询问中边权与当前边权相等的边,因为当前处理的这些询问的边权都相等,所以我们按照询问的 id 分组单独讨论,对于每个 id 来说,将这些边权相等的边都加入到并查集中后如果发现有环的话,那就说明第 id 个询问的答案是 NO ,如此处理即可

需要注意的是,上面的橙色的字,只是判断每个询问的可行性用的,并不属于最小生成树的过程,所以在进行上述插入过程后,需要及时撤销

因为涉及到了并查集的撤销,所以不能进行路径压缩,总的时间复杂度就是 mlogm 的

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=5e5+100;struct Edge
{int u,v,w,id;bool operator<(const Edge& t)const{if(w!=t.w)return w<t.w;return id<t.id;}
}edge[N],qu[N];struct revo
{int fax,fay;int rkx,rky;
};int f[N],rk[N],tot;bool ans[N];stack<revo>st;int find(int x)
{return f[x]==x?x:find(f[x]);
}bool merge(int x,int y)
{int xx=find(x),yy=find(y);if(xx==yy)return false;revo temp;temp.fax=xx,temp.fay=yy;temp.rkx=rk[xx],temp.rky=rk[yy];st.push(temp);if(rk[xx]>rk[yy])swap(xx,yy);f[xx]=yy;rk[yy]=max(rk[yy],rk[xx]+1);return true;
}void revocation(int k)
{while(k--){revo node=st.top();st.pop();f[node.fax]=node.fax;f[node.fay]=node.fay;rk[node.fax]=node.rkx;rk[node.fay]=node.rky;}
}void init()
{for(int i=1;i<N;i++){f[i]=i;rk[i]=1;}
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);int q;scanf("%d",&q);for(int i=1;i<=q;i++){ans[i]=true;int k;scanf("%d",&k);while(k--){int num;scanf("%d",&num);tot++;qu[tot]=edge[num];qu[tot].id=i;}}sort(edge+1,edge+1+m);sort(qu+1,qu+1+tot);int pos=1;//记录qu数组的下标 for(int i=1;i<=m;i++){int cnt=0;//共需要撤销多少条边while(qu[pos].w==edge[i].w){if(qu[pos].id!=qu[pos-1].id)//如果相邻两个询问的边不属于同一个组,则需要撤销 {revocation(cnt);cnt=0;}if(!merge(qu[pos].u,qu[pos].v))//如果询问的两个点早已经合并,说明当前的边不是必须的,更新答案 ans[qu[pos].id]=false;else//否则在需要撤销的数量上加一 cnt++;pos++;}revocation(cnt);merge(edge[i].u,edge[i].v);}for(int i=1;i<=q;i++)if(ans[i])puts("YES");elseputs("NO");return 0;
}

CodeForces - 892E Envy(可撤销并查集)相关推荐

  1. CodeForces - 1445E Team-Building(可撤销并查集)

    题目链接:点击查看 题目大意:给出一张有 n 个点和 m 条边的图,每个点都有一个种类,共有 k 个种类,现在要从 k 个种类中每次选出两种,对所有 C( k , 2 ) 种组合单独讨论,对于选出的两 ...

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

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

  3. 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)

    题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...

  4. 线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解

    题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2) 首先我们考虑这种动态加边删边 ...

  5. 洛谷P7518:宝石(倍增、可撤销并查集)

    解析 算法一 定义 upx,kup_{x,k}upx,k​ 为节点 xxx 从自己的颜色所在位置在返祖链上往后跳 2k2^k2k 个颜色到达的节点. 可以像倍增一样的求解. 这样对于一次询问 (s,t ...

  6. CF603E-Pastoral Oddities【CDQ分治,可撤销并查集】

    正题 题目链接:https://www.luogu.com.cn/problem/CF603E 题目大意 开始时有nnn个点,没有边. 依次加入mmm条带权的边,每次加入后询问是否存在一个边集,满足每 ...

  7. BZOJ4358: permu(带撤销并查集 不删除莫队)

    题意 题目链接 Sol 感觉自己已经老的爬不动了.. 想了一会儿,大概用个不删除莫队+带撤销并查集就能搞了吧,\(n \sqrt{n} logn\)应该卡的过去 不过不删除莫队咋写来着?....跑去学 ...

  8. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

  9. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

最新文章

  1. 用dw中html设置背景,Dreamweaver 教程-CSS背景属性(background)
  2. 00-elasticsearch的pom文件
  3. java函数实现进制转换与java实现八进制到十进制的转换(百练OJ:2735:八进制到十进制)
  4. [Python人工智能] 二十一.Word2Vec+CNN中文文本分类详解及与机器学习(RF\DTC\SVM\KNN\NB\LR)分类对比
  5. Vim升华之树形目录插件NERDTree安装图解
  6. cls certificate.php,php加密解密处理类
  7. WAMP本地环境升级php版本操作步骤(详细)
  8. Eclipse最全快捷键
  9. PhoneGap API帮助文档翻译—Capture (采集)
  10. python学习笔记 day20 常用模块(六)
  11. [HDU 4842]--过河(dp+状态压缩)
  12. 用Python制作五子棋人机对弈(人工智障版和升级AI版)
  13. springcloud如何搭建支付宝pay-service微服务
  14. 软件开发测试基础知识
  15. 第四百三十五章 灭龙魔宫
  16. 华为鸿蒙vivo,vivo的OriginOS系统开启公测 华为鸿蒙OS迎来劲敌
  17. Linux使用C语言实现ls命令
  18. 从键盘读入学生成绩,找出最高分, 并输出学生成绩等级
  19. 这里整理了基于java平台的常用资源
  20. Python tkinter窗口最大化处理

热门文章

  1. 卫生统计学v是什么意思_四川大学华西公共卫生学院报考常见问题答疑
  2. MySQL高级 - 常用工具 - mysqlshow
  3. 什么是Starter
  4. 反射获取成员变量并使用【应用】
  5. RocketMQ的Producer详解之分布式事务消息(原理分析)
  6. GraphQL入门之什么是GraphQL?
  7. ServletContext_概述
  8. java properties 属性,java 读取 properties 属性资料
  9. linux中ps aux和ps -ef下显示的意义
  10. MakeFile中文手册(免费下载)-徐海兵整理