P4334 [COI2007] Policija

题意

一个无重边的无向图,每次询问删掉一条边或删掉一个点后两个点是否联通。

思路

连通性问题,我们可以考虑使用广义圆方树解决。

  1. 对于删掉一个点的情况:

我们先跑 tarjan 建出圆方树。如何判断两点在删去一个点后在树上的连通性?当且仅当被删去的点在两点间的路径上。根据圆方树的性质,如果被删点在一个点双连通分量中,它是符合上面的判断条件的。

所以,我们只需要建出圆方树,判断这个点是否在询问的两点间的路径上就行了。

  1. 对于删掉一条边的情况:

考虑我们建出来的广义圆方树是一种怎样的形态。它一定是圆方点交错的形式。换句话说,一条边若不在点双连通分量内,它就会变成一个方点,并连接其原来的两个点。

换句话说,我们把一条边转化成了一个点。于是我们就可以像上面处理点一样处理了。

实现

判断一个点是否在两点路径上,我们可以用树剖实现。具体来讲,在跳LCA的过程中判断被删点是否在起终点之间,我们用链首和深度判断即可。

由于题目查询边的给出方式约束,我们可以用 map 实现查询边是否在点双内。代码中,minmax 函数为 C++11 语法,其返回值为一个排好序后的 pair 。

整体时间复杂度为 \(O(n+q(\log n+\log m))\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=2e5+10,maxm=5e5+10;
typedef pair<int,int> pii;
int n,m;
struct gragh{
int ecnt,head[maxn],to[maxm<<1],nxt[maxm<<1];
inline void addedge(int a,int b){
to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
to[++ecnt]=a,nxt[ecnt]=head[b],head[b]=ecnt;
}
}G1,G2;
int tot,cnt,st[maxn],dfn[maxn],low[maxn];
map<pii,int> mp;
void tarjan(int x,int f){
dfn[x]=low[x]=++tot;
st[++st[0]]=x;
for(int i=G1.head[x];i;i=G1.nxt[i]){
int u=G1.to[i];
if(u==f)continue;
if(!dfn[u]){
tarjan(u,x);
low[x]=min(low[x],low[u]);
if(low[u]>=dfn[x]){
cnt++;
if(low[u]>dfn[x]) mp.insert(make_pair(minmax(u,x),cnt));
G2.addedge(cnt,x);
int now=-1;
while(now^u)
now=st[st[0]--],G2.addedge(now,cnt);
}
}else low[x]=min(low[x],dfn[u]);
}
}
int fa[maxn],dep[maxn],top[maxn],son[maxn],siz[maxn];
void dfs1(int x,int f){
fa[x]=f,dep[x]=dep[f]+1;siz[x]=1;
for(int i=G2.head[x];i;i=G2.nxt[i]){
int u=G2.to[i];
if(u==f)continue;
dfs1(u,x);
siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
void dfs2(int x,int topf){
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=G2.head[x];i;i=G2.nxt[i]){
int u=G2.to[i];
if(u==fa[x] or u==son[x]) continue;
dfs2(u,u);
}
}
inline bool LCA(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(top[x]==top[z] and dep[z]<=dep[x]) return 1;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
if(top[x]==top[z] and dep[z]>=dep[y] and dep[z]<=dep[x]) return 1;
return 0;
}
inline void work(){
n=cnt=read(),m=read();
for(int i=1;i<=m;i++) G1.addedge(read(),read());
tarjan(1,0);
dfs1(1,0);
dfs2(1,1);
int Q=read();
while(Q--)
if(read()==1){
int x=read(),y=read();
map<pii,int>::iterator it=mp.find(minmax(read(),read()));
if(it==mp.end()) puts("yes");
else puts(LCA(x,y,(*it).second)?"no":"yes");
}else{
int x=read(),y=read(),z=read();
puts(LCA(x,y,z)?"no":"yes");
}
}
}
signed main(){
star::work();
return 0;
}

P4334 [COI2007] Policija的更多相关文章

  1. [hdu P4334] Trouble

    [hdu P4334] Trouble Hassan is in trouble. His mathematics teacher has given him a very difficult pro ...

  2. 洛谷 P1823 [COI2007] Patrik 音乐会的等待

    洛谷 P1823 [COI2007] Patrik 音乐会的等待 洛谷传送门 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A ...

  3. 洛谷 P1823 [COI2007] Patrik 音乐会的等待 题解

    P1823 [COI2007] Patrik 音乐会的等待 题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相 ...

  4. 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1333275 这个题不是很 ...

  5. [COI2007] Sabor

    下面给出这道一脸不可做的题的鬼畜性质: 1)对于一个点来说,其归属状态是确定的:走不到.A党或B党 .(黑白格染色) 方便起见,将包含所有不可达的点的极小矩形向外扩展一圈,设为矩形M. 2)矩形M的最 ...

  6. P1823 [COI2007] Patrik 音乐会的等待 单调栈 洛谷luogu

    题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. ...

  7. 【洛谷】【单调栈】P4333 [COI2007] Patrik

    --接上一篇题解,[洛谷][单调栈]P1823音乐会的等待 关于题目大意在上一篇题解里已经说清楚了,这里不再多阐述 想看题目->戳这里 [算法分析:] 在对元素a进行判断时,如果它与栈顶元素相等 ...

  8. 洛谷P1823 [COI2007] Patrik 音乐会的等待

    https://www.luogu.org/problemnew/show/P1823 自己只会一个log的 设取的人的位置分别是l,r(l<r) 这个做法大概是考虑枚举r,设法对于每个r求出有 ...

  9. [COI2007] Patrik 音乐会的等待 (单调栈,模拟)

    题目描述 N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的. ...

随机推荐

  1. ES6函数参数

    之前在看Vue2.0的时候,就被很多的箭头函数困扰,一直不知道是怎么回事,虽然箭头函数四个字在我耳边一直转圈,今天小编整理整理箭头函数里面的常见用法和表现形式,在这个Vue3.0已经到来的一段时间,希 ...

  2. 【逆向实战】恶意勒索软件分析_披着羊皮的狼_被注入恶意代码的apk

    /文章作者:Kali_MG1937 QQ:3496925334 CNBLOG博客号:ALDYS4/ 今天逛某论坛的时候发现了一篇求助贴 有意思,好久没分析过恶意软件了 今天就拿它来练练手 反编译工具 ...

  3. GoLang:通过url将值从view层(.tpl)传递到controller层

    beego框架 1.定义路由: beego.Router("/UpdateState/:statename/:id", &controllers.ContentContro ...

  4. Mysql_SQLyog 数据库的创建

    1.创建数据库 CREATE DATABASE [IF NOT EXISTS] westos; 2.删除数据库 DROP DATABASE [IF EXISTS] westos; 3.使用数据库 -- ...

  5. SVN报错“Failed to run the WC DB work queue associated with”解决办法

    最近在更新SVN上的ISO代码时,失败报错:  Failed to run the WC DB work queue associated with "目录/文件",clean u ...

  6. 扩展ADO.net实现对象化CRUD(.net core/framework)

    扩展ADO.net实现对象化CRUD(.net core/framework) 安装nuget包:CRL using CRL; 实现数据操作 获取数据访问连接IDbConnection dbConne ...

  7. ceph-csi源码分析(6)-rbd driver-nodeserver分析(下)

    更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi源码分析(6)-rbd driver-nodeserver分析(下) 当c ...

  8. Pytest学习笔记10-生成html报告

    前言 在pytest中,如何生成html测试报告呢,pytest提供了pytest-html插件,可以帮助我们生成测试报告,当然,如果希望生成更加精美的测试报告,我们还可以使用allure生成报告,下 ...

  9. 15、oracle多表查询

    15.0.实验建表: --父表 create table class( id number(10)constraint class_id_pk primary key, class_name varc ...

  10. 详解C++中的多态和虚函数

    一.将子类赋值给父类 在C++中经常会出现数据类型的转换,比如 int-float等,这种转换的前提是编译器知道如何对数据进行取舍.类其实也是一种数据类型,也可以发生数据转换,但是这种转换只有在 子类 ...