Description

Byteasar是一个很纠结的人。每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路。Byteasar最近听说了Bytetown的修路计划,他可能是唯一一个为此感到高兴的人——他有机会消除他的烦恼。

在Byteasar一共有n个岔口,连接着m条双向道路。两条路径完全不同当且仅当他们没有公共的道路(但是允许经过相同的岔口)。

Byteasar想知道:对于两个岔口x y,是否存在一对完全不同的路径。

Input

第一行3个整数:n, m, z (2<=n<=100000, 1<=m,z<=100000),分别代表:n个岔口,m条边,事件数z。岔口编号为1~n。

下面m行:ai, bi (1<=ai,bi<= n, ai!=bi),描述一条边

然后下面z行描述事件:ti, ci, di (t='Z' or 'P', 1<=ci,di<=n, ci!=di)。事件按照时间排序。

  • t='Z',表示删除一条边(ci, di),保证这条边之前没有被删除。注意,边可以被全部删除!
  • t='P',询问是否存在从ci到di的一对完全不同的路径。

Output

对于每组询问,如果存在,输出TAK,否则输出NIE

逆着操作顺序加边,同时并查集维护连通性和边双连通分量
预处理出按加边顺序得到的生成森林,在上面把每个连通块定向为有根树并标上深度
正式加边时,若两侧不连通则标为联通,否则将边的两端在生成树上的路径并成同一个边双连通分量
查询时可以直接判断两点是否在同个边双连通分量内

#include<bits/stdc++.h>
char buf[],*ptr=buf-;
int _(){
int x=,c=*++ptr;
while(c<)c=*++ptr;
while(c>)x=x*+c-,c=*++ptr;
return x;
}
int _o(){
int c=*++ptr;
while(c<'A'||c>'Z')c=*++ptr;
return c;
}
const int N=;
int es[N*],enx[N*],ev[N*],e0[N],ep=,del[N];
int n,m,q,qs[N][],f1[N],f2[N],fa[N],ap=,dep[N];
bool ed[N],as[N];
int get(int*f,int x){
int a=x,c;
while(x!=f[x])x=f[x];
while(x!=f[a])c=f[a],f[a]=x,a=c;
return x;
}
struct edge{
int a,b,id;
bool operator<(edge e)const{return a!=e.a?a<e.a:b<e.b;}
void chk(){
int x=get(f1,a),y=get(f1,b);
if(x!=y){
f1[x]=y;
ev[id<<]=ev[id<<|]=;
}
}
void ins(){
int x=get(f1,a),y=get(f1,b);
if(x!=y){
f1[x]=y;
return;
}
a=get(f2,a);b=get(f2,b);
while(a!=b){
if(dep[a]<dep[b])b=f2[b]=get(f2,fa[b]);
else a=f2[a]=get(f2,fa[a]);
}
}
}e[N];
void dfs(int w){
ed[w]=;
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(!ed[u]&&ev[i])fa[u]=w,dep[u]=dep[w]+,dfs(u);
}
}
void ae(){
int a=_(),b=_();
if(a>b)std::swap(a,b);
e[ep>>]=(edge){a,b,ep>>};
es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
}
void query(int a,int b){
as[ap++]=(get(f2,a)==get(f2,b));
}
int main(){
fread(buf,,sizeof(buf),stdin);
n=_();m=_();q=_();
for(int i=;i<=m;++i)ae();
std::sort(e+,e+m+);
for(int i=,a,b;i<=q;++i){
if(qs[i][]=(_o()=='Z')){
a=_();b=_();
if(a>b)std::swap(a,b);
a=std::lower_bound(e+,e+m+,(edge){a,b})-e;
++del[a];
qs[i][]=a;
}else{
qs[i][]=_();
qs[i][]=_();
}
}
for(int i=;i<=n;++i)f1[i]=i;
for(int i=;i<=m;++i){
while(del[i])i+=del[i];
if(i<=m)e[i].chk();
}
for(int i=q;i;--i)if(qs[i][])e[qs[i][]].chk();
for(int i=;i<=n;++i)if(!ed[i])dfs(i);
for(int i=;i<=n;++i)f1[i]=f2[i]=i;
for(int i=;i<=m;++i){
while(del[i])i+=del[i];
if(i<=m)e[i].ins();
}
for(int i=q;i;--i)if(qs[i][])e[qs[i][]].ins();else query(qs[i][],qs[i][]);
while(ap)puts(as[--ap]?"TAK":"NIE");
return ;
}

3069: [Pa2011]Hard Choice 艰难的选择的更多相关文章

  1. BZOJ3069: [Pa2011]Hard Choice 艰难的选择

    Description Byteasar是一个很纠结的人.每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路.Byteasar最近听说了Bytet ...

  2. UVA 1175 Ladies' Choice 女士的选择(稳定婚姻问题,GS算法)

    题意: 给出每个男的心目中的女神排序,给出每个女的心目中的男神排序,即两个n*n的矩阵,一旦任意两个非舞伴的男女同学觉得对方都比现任舞伴要好,他们就会抛弃舞伴而在一起.为了杜绝这种现象,求每个男的最后 ...

  3. 题解 洛谷 P6351 【[PA2011]Hard Choice】

    删边操作不好处理,所以先将操作倒序,将删边转化为加边. 考虑对于两个点的询问,若这两点不连通或这两个点分别处于两个不同的边双连通分量中(两点间存在桥)时,是不满足题目要求的. 可以用\(LCT\)来维 ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. 6个原因说服你选择PostgreSQL9.6

    PostgreSQL9.6在前些日子发布了, 社区为该版本的重大更新付诸良多, 发布日志一如既往的长,我挑选了6个重要的更新, 这些或许能够帮助你更好的使用PostgreSQL. 并行: 并行应该是这 ...

  6. 选择——ERP信息系统选型

    做一次选择并不难,难的是做一次坚定而正确的选择.TCL电脑公司的ERP软件选型就是一次正确而艰难的选择过程.让我们从头说起吧!­ 业界都知道TCL电脑是IT行业的新入行者,更知道TCL的另一个诠释:& ...

  7. python random从集合中随机选择元素

    1.使用python random模块的choice方法随机选择某个元素 from random import choice foo = ['a', 'b', 'c', 'd', 'e'] print ...

  8. Python switch(多分支选择)的实现

    Python 中没有 switch/case 语法,如果使用 if/elif/else 会出现代码过长.不清晰等问题. 而借助字典就可以实现 switch 的功能 示例: def case1(): # ...

  9. Django框架(十一)-- 补充:inclusion_tag、defer、only、choice、事务、创建多对多的第三张表、mvc和mtv模式

    一.inclusion_tag 1.作用 用于生成HTML片段,是数据由参数传入而变成动态 2.使用 # 1.app下新建一个模块,templatetags # 2.创建一个py文件(mytag.py ...

随机推荐

  1. java中join用法

    今天又把join的用法大概看了一下,其实理解起来,还是比较简单.用个简单的例子说明一下吧. 1.通过下面的例子,可以看到说出结果中首先全部是是Thread-1,之后才会是Thread-2,这是因为在主 ...

  2. Docker的安装及操作

    1. 在Ubuntu中安装Docker 更新ubuntu的apt源索引 sudo apt-get update 安装包允许apt通过HTTPS使用仓库 sudo apt-get install \ a ...

  3. GitHub原来也可以用SVN客户端的.

    不知道是不是自己真的太宅了. 一直以为只能用git client 来clone github工程的.  偶然今日发现还可以用 SVN 来下载的. 果断一试. 太好用了. 这回windows 上不用纠结 ...

  4. vim简单的文本编辑命令

    <blockquote>:e! enter</blockquote>消除所有这次编辑的,回到原来文件的样子.不过此文件还是打开状态.<blockquote>:q! ...

  5. maven scope-一览表

  6. html5大纲算法(目录树)

    看了<CSS那些事儿>我一直遵循着给每个板块写一个h标签,并保持层次,比如导航条.焦点图我都写了一个缩进隐藏的h标签.这种规范一般人根本看不出来,即使是行内的大多数人也觉得没有必要.可是我 ...

  7. Map集合学习

    Java中常用的Map实现类主要有:HashMap.HashTable.TreeMap.LinkedHashMap. 一:HashMap HashMap介绍 HashMap的底层其实是“链表的数组”, ...

  8. 原生Ajax使用

    Ajax基础 Ajax(Asynchronous JavaScript And XML)概念:通过XMLHttpRequest对象向服务器提出请求并处理响应,进行页面的局部更新. AJAX都有哪些优点 ...

  9. BZOJ1336 Balkan2002 Alien最小圆覆盖 【随机增量法】*

    BZOJ1336 Balkan2002 Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=100000, ...

  10. 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)

    在上一篇文章 深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsync 部分) 中我们发现 Dispatcher.Invoke 方法内部是靠 Dispatcher.Pu ...