codeforces 892E(离散化+可撤销并查集)
题意
给出一个n个点m条边的无向联通图(n,m<=5e5),有q(q<=5e5)个询问
每个询问询问一个边集{Ei},回答这些边能否在同一个最小生成树中
分析
要知道一个性质,就是权值不同的边之间是独立的,即权值为x的所有边的选取不影响权值>x的边的选取
于是我们可以把所有询问离线,按边权排序,对于当前处理的边权,如果有某个询问在其中,那么我们把这些边加进去看有没有环,如果有,那么这个询问就被叉掉了,当然处理完了还要把刚才的操作撤销掉
处理了当前权值x的所有询问,最后别忘了把权值为x的边做kruskal算法加进去
这样时间复杂度是带log的(按秩合并的可撤销并查集的复杂度)
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5;
int f[maxn+],sz[maxn+];
int ans[maxn+];
struct Edge
{
int u,v,w;
}edge[maxn+];
vector<int> b[maxn+];
vector<int> q[maxn+];
struct question
{
int id,from,to;
};
vector<question> a[maxn+];
int n,m,Q;
bool cmp(const int x,const int y)
{
return edge[x].w<edge[y].w;
}
stack<pair<int,int> > s;
int find(int x)
{
if(f[x]==x) return x;else return find(f[x]);
}
void Union(int x,int y)
{
if(sz[x]<sz[y]) f[x]=y,sz[y]+=sz[x],s.push(make_pair(x,y));
else f[y]=x,sz[x]+=sz[y],s.push(make_pair(y,x));
}
void remove()
{
pair<int,int> u=s.top();
s.pop();
f[u.first]=u.first;
sz[u.second]-=sz[u.first];
}
bool check(int id,int from,int to)
{
bool ans=;
int sum=;
for(int i=from;i<=to;++i)
{
int p=q[id][i];
int x=find(edge[p].u),y=find(edge[p].v);
if(x!=y) Union(x,y),++sum;else ans=;
}
for(int i=;i<=sum;++i) remove();
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;++i)
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w),b[edge[i].w].push_back(i);
scanf("%d",&Q);
for(int i=;i<=Q;++i)
{
q[i].clear();
int num,x;
scanf("%d",&num);
while(num--)
{
scanf("%d",&x);
q[i].push_back(x);
}
sort(q[i].begin(),q[i].end(),cmp);
int from=;
for(int j=;j<q[i].size();++j)
if(edge[q[i][j]].w!=edge[q[i][j-]].w)
{
a[edge[q[i][j-]].w].push_back({i,from,j-});
from=j;
}
a[edge[q[i][q[i].size()-]].w].push_back({i,from,q[i].size()-});
}
for(int i=;i<=n;++i) f[i]=i,sz[i]=;
for(int i=;i<=maxn;++i)
{
for(int j=;j<a[i].size();++j)
if(!check(a[i][j].id,a[i][j].from,a[i][j].to)) ans[a[i][j].id]=;
for(int j=;j<b[i].size();++j)
{
int p=b[i][j];
int x=find(edge[p].u),y=find(edge[p].v);
if(x!=y) Union(x,y);
}
}
for(int i=;i<=Q;++i)
if(ans[i]) printf("NO\n");else printf("YES\n");
return ;
}
codeforces 892E(离散化+可撤销并查集)的更多相关文章
- Codeforces 938G 线段树分治 线性基 可撤销并查集
Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...
- CodeForces892E 可撤销并查集/最小生成树
http://codeforces.com/problemset/problem/892/E 题意:给出一个 n 个点 m 条边的无向图,每条边有边权,共 Q 次询问,每次给出 ki 条边,问这些边 ...
- 2019牛客第八场多校 E_Explorer 可撤销并查集(栈)+线段树
目录 题意: 分析: @(2019牛客暑期多校训练营(第八场)E_Explorer) 题意: 链接 题目类似:CF366D,Gym101652T 本题给你\(n(100000)\)个点\(m(1000 ...
- POJ 1733 Parity game(离散化+带权并查集)
离散化+带权并查集 题意:长度为n的0和1组成的字符串,然后问第L和R位置之间有奇数个1还是偶数个1. 根据这些回答, 判断第几个是错误(和之前有矛盾)的. 思路:此题同HDU 3038 差不多,询问 ...
- bzoj2049 线段树 + 可撤销并查集
https://www.lydsy.com/JudgeOnline/problem.php?id=2049 线段树真神奇 题意:给出一波操作,拆边加边以及询问两点是否联通. 听说常规方法是在线LCT, ...
- BZOJ4358: permu(带撤销并查集 不删除莫队)
题意 题目链接 Sol 感觉自己已经老的爬不动了.. 想了一会儿,大概用个不删除莫队+带撤销并查集就能搞了吧,\(n \sqrt{n} logn\)应该卡的过去 不过不删除莫队咋写来着?....跑去学 ...
- 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic
本题可化成更一般的问题:离线动态图询问连通性 当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常 ...
- 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)
题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...
- 【BZOJ4025】二分图(可撤销并查集+线段树分治)
题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...
随机推荐
- LibreOJ #109. 并查集
题目描述 这是一道模板题. 维护一个 nnn 点的无向图,支持: 加入一条连接 uuu 和 vvv 的无向边 查询 uuu 和 vvv 的连通性 由于本题数据较大,因此输出的时候采用特殊的输出方式:用 ...
- DHCP server工作原理
1.CLIENT首先发出广播的DHCPDISCOVER报文,广播的目的是让DHCP SERVER能够收到这个请求报文.在这个报文中,CLIENT可以在"选项"字段中加入" ...
- JOIN和UNION的区别
join 是两张表根据条件相同的部分合并生成一个记录集. SELECT Websites.id, Websites.name, access_log.count, access_log.dateFRO ...
- qobject_cast
void QLadderDiagramItem::GetMainForm(DoType sourceType){ for each (QWidget *w in qApp->topLevelWi ...
- JavaEE-01 JSP动态网页基础
学习要点 B/S架构的基本概念 Web项目的创建和运行 JSP页面元素 MyEclipse创建和运行Web项目 Web程序调试 Web简史 web前端技术演进三阶段 WEB 1.0:信息广播. WEB ...
- python interview questions
referce:python interview questions top 50 refercence:python interview questions top 15 summary Q: wh ...
- Node.js快速生成26个字母
const buf1 = Buffer.allocUnsafe(26); for (let i = 0; i < 26; i++) { // 97 是 'a' 的十进制 ASCII 值. buf ...
- GO:interface
一.感受接口 type Usb interface { Connect() Disconnect() } // 手机 type Phone struct {} // 相机 type Camera st ...
- python对象销毁(垃圾回收)
Python 使用了引用计数这一简单技术来跟踪和回收垃圾. 在 Python 内部记录着所有使用中的对象各有多少引用. 一个内部跟踪变量,称为一个引用计数器. 当对象被创建时, 就创建了一个引用计数, ...
- day15-python之变量和递归
1.局部变量与全局变量 #!/usr/bin/env python # -*- coding:utf-8 -*- # name='lhf' # def change_name(): # global ...