选择 (动态树)

题目描述:

现在,我想知道自己是否还有选择。

给定n个点m条边的无向图以及顺序发生的q个事件。

每个事件都属于下面两种之一:

1、删除某一条图上仍存在的边

2、询问是否存在两条边不相交的路径可以从点u出发到点v

输入:

第一行三个整数n,m,q

接下来m行,每行两个整数u,v,表示u和v之间有一条边

接下来q行,每行一个大写字母o和2个整数u、v,依次表示按顺序发生的q个事件:

当o为’Z’时,表示删除一条u和v之间的边

当o为’P’时,表示询问是否存在两条边不相交的路径可以从点u出发到点v

输出:

对于每组询问,如果存在,输出Yes,否则输出No

样例输入:

7 8 7

1 2

1 3

1 4

2 3

3 4

3 7

7 4

5 6

Z 1 4

P 1 3

P 2 4

Z 1 3

P 1 3

Z 6 5

P 5 6

样例输出:

Yes

Yes

No

No

数据规模和约定:

对于20%的数据,max(n,m,q)<=100

对于全部数据,max(n,m,q)<=100000

思路:离线做,用动态树维护连通性,对于已经在同一个连通分块里面的两个点,将这两个点之间的所有点全部缩成一个点,这个点就是最上边的那个,也就是split(x,y)以后的y,然后询问的时候,倒着做,拆边变成加边,对于两个询问点,询问他们是不是在同一个缩的点内,如果是,那么他们就有两条边不相交的路线。

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<map>
  7 struct edge{
  8     int u,v,id;
  9 }e[200005],ask[200005];
 10 std::map<int,std::map<int,int> >mp;
 11 int n,m,q,ts[500005],tx[500005];
 12 int ch[200005][2],fa[200005],f[200005],st[200005],rev[200005],ans[200005];
 13 int read(){
 14     char ch=getchar();int t=0,ff=1;
 15     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) ff=-1;ch=getchar();}
 16     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
 17     return t*ff;
 18 }
 19 int Find(int x){
 20     int top=0,i;
 21     if (x==f[x]) return x;
 22     for (i=x;f[i]!=i;i=f[i]){
 23         ts[++top]=i;
 24     }
 25     int key=i;
 26     for (int i=top;i>=1;i--)
 27      f[ts[i]]=key;
 28     return key;
 29 }
 30 bool isroot(int x){
 31     fa[x]=Find(fa[x]);
 32     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 33 }
 34 void updata(int x){}
 35 void pushdown(int x){
 36     int l=ch[x][0],r=ch[x][1];
 37     if (rev[x]){
 38         rev[x]^=1;
 39         rev[l]^=1;rev[r]^=1;
 40         std::swap(ch[x][0],ch[x][1]);
 41     }
 42 }
 43 void rotate(int x){
 44     int y=fa[x],z=fa[y],l,r;
 45     if (ch[y][0]==x) l=0;else l=1;r=l^1;
 46     if (!isroot(y)){
 47         if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
 48     }
 49     fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
 50     ch[y][l]=ch[x][r];ch[x][r]=y;
 51     updata(y);updata(x);
 52 }
 53 void splay(int x){
 54     int top=0;st[++top]=x;
 55     for (int i=x;!isroot(i);i=fa[i]){
 56         st[++top]=fa[i];
 57     }
 58     for (int i=top;i>=1;i--) pushdown(st[i]);
 59     while (!isroot(x)){
 60         int y=fa[x],z=fa[y];
 61         if (!isroot(y)){
 62             if (ch[y][0]==x^ch[z][0]==y) rotate(x);
 63             else rotate(y);
 64         }
 65         rotate(x);
 66     }
 67 }
 68 void access(int x){
 69     for (int t=0;x;t=x,fa[x]=Find(fa[x]),x=fa[x]){
 70         splay(x);
 71         ch[x][1]=t;
 72         updata(x);
 73     }
 74 }
 75 int find(int x){
 76     access(x);splay(x);
 77     while (ch[x][0]) x=ch[x][0];
 78     return x;
 79 }
 80 void makeroot(int x){
 81     access(x);splay(x);rev[x]^=1;
 82 }
 83 void split(int x,int y){
 84     makeroot(x);access(y);splay(y);
 85 }
 86 void bfs(int x){
 87     int h=1,t=1;tx[h]=x;
 88     for (;h<=t;h++){
 89         if (ch[tx[h]][0]) tx[++t]=ch[tx[h]][0];
 90         if (ch[tx[h]][1]) tx[++t]=ch[tx[h]][1];
 91     }
 92     for (int i=1;i<=t;i++){
 93         if (i!=1) fa[tx[i]]=0;
 94         f[tx[i]]=x;ch[tx[i]][0]=ch[tx[i]][1]=0;
 95     }
 96 }
 97 void link(int x,int y){
 98     x=Find(x);y=Find(y);
 99     if (find(x)!=find(y)){
100         makeroot(x);
101         fa[x]=y;
102     }else{
103         split(x,y);
104         bfs(y);
105     }
106 }
107 int main(){
108     n=read();m=read();q=read();
109     for (int i=1;i<=n;i++) f[i]=i;
110     for (int i=1;i<=m;i++){
111         e[i].u=read();e[i].v=read();
112         if (e[i].u>e[i].v) std::swap(e[i].u,e[i].v);
113         mp[e[i].u][e[i].v]++;
114     }
115     char opt[2];
116     for (int i=1;i<=q;i++){
117         scanf("%s",opt+1);
118         if (opt[1]==‘Z‘) ask[i].id=1;
119         else ask[i].id=2;
120         ask[i].u=read();ask[i].v=read();
121         if (ask[i].u>ask[i].v) std::swap(ask[i].u,ask[i].v);
122         if (ask[i].id==2) continue;
123         if (mp[ask[i].u][ask[i].v]>0) mp[ask[i].u][ask[i].v]--;
124         else ask[i].id=0;
125     }
126     for (int i=1;i<=m;i++)
127      if (mp[e[i].u][e[i].v]>0){
128             link(e[i].u,e[i].v);
129      }
130     for (int i=q;i>=1;i--)
131      if (ask[i].id==1){
132             link(ask[i].u,ask[i].v);
133      }else
134      if (ask[i].id==2)
135      {
136             if (Find(ask[i].u)!=Find(ask[i].v)) ans[i]=2;
137             else ans[i]=1;
138      }
139     for (int i=1;i<=q;i++)
140      if (ask[i].id==2){
141             if (ans[i]==1) puts("Yes");
142             else puts("No");
143      }
144 }
时间: 2024-12-28 12:43:03

选择 (动态树)的相关文章

动态树 Link-Cut Trees

动态树 动态树问题, 即要求我们维护一个由若干棵子结点无序的有根树组成的森林. 要求这个数据结构支持对树的分割.合并,对某个点到它的根的路径的某些操作,以及对某个点的子树进行的某些操作. 在这里我们考虑一个简化的动态树问题,它只包含对树的形态的操作和对某个点到根的路径的操作: 维护一个数据结构,支持以下操作: • MAKE TREE() — 新建一棵只有一个结点的树. • CUT(v) — 删除 v 与它的父亲结点 parent(v) 的边,相当于将点 v 的子树分离了出来. • JOIN(v,

extjs动态树 动态grid 动态列

由于项目需要做一个动态的extjs树.列等等,简而言之,就是一个都是动态的加载功能, 自己琢磨了半天,查各种资料,弄了将近两个星期,终于做出来了 首先,想看表结构,我的这个功能需要主从两张表来支持 代码目录表: CREATE TABLE SYS_T01_CODECONTENT ( ID NUMBER NOT NULL, PID NUMBER NOT NULL, TABLENAME VARCHAR2(50 BYTE), ZH_CN VARCHAR2(200 BYTE), ENABLE CHAR(1

【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态树分治

题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了. 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决. 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来.在游戏中,幽香可能在空地上增加或者减少一些军队.同时,幽香可以在一个空地上放置一个补给站. 如果补给站在点u上,并

如何利用FineReport制作动态树报表

在对数据字段进行分类管理时,利用动态树折叠数据是一个很好的方法,也就是点击数据前面的加号才展开对应下面的数据,如下图.那这样的效果在制作报表时该如何实现呢? 下面以报表工具FineReport为例介绍. 思路: 通过将模版设置为组织树报表,然后通过设置树节点按钮,最好通过数据分析预览或者form表单预览即可查看效果. 步骤: 1.  初步建立模板 建立模板就相当于建立一个excel的sheet,只不过是cpt的形式.把相应的字段拖到单元格内. 2.  增加树节点按钮 通过设置树节点按钮来实现折叠

【bzoj3589】动态树 树链剖分+线段树

题目描述 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0:这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1:小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次. 输入 第一行一个整数n(1<=n<=200,000), 即节点数. 接下来n-1行, 每行两个数字u,

数据结构(动态树):COGS 27. [WC 2006] 水管局长

27. [WC 2006] 水管局长 ★★★☆   输入文件:tube.in   输出文件:tube.out   简单对比时间限制:3 s   内存限制:128 MB [问题描述 ] SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从 x 处运往 y 处,嘟嘟需要为供水公司找到一条从 A 至 B 的水管的路径,接着通过信息化的控制中心通知路径上的水管进入准备送水状态,等到路径上每一条水管都准备好了,

bzoj 2594: [Wc2006]水管局长数据加强版 动态树

2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 934  Solved: 291[Submit][Status] Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的路径,接着通过信息化的控制中心通知路径上的水管进入准备送水状态,等到路径

【bzoj4012】[HNOI2015]开店 动态树分治+二分查找

题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群.很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n个地方,编号为 1 到 n,被 n-1 条带权的边连接起来.每个地方都住着一个妖怪,其中第 i 个地方的妖怪年龄是 x_i.妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻.所以这个树所有顶点的

动态树LCT小结

最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点间的关系,将树转化成连续的区间,再加以其它的数据结构,便能以较快的速度处理序列的修改和查询. 而动态树的问题,是包括了树的合并和拆分操作.这个时候,通过预处理实现的静态树的序列算法不能满足我们的要求,于是我们需要一颗‘动态’的树,能在O(logN)的时间复杂度,处理所有操作. Splay实现的Lin