P2542 【[AHOI2005]航线规划】

一个无向图,m个操作

  • 删去一条边
  • 给定两个点,求有多少边使得如果这条边不存在,给定的两个点不连通

一般这种删边的题目,考虑逆序加边处理

在删完的图中,任意找出一棵生成树,对它进行树链剖分

然后需要把不再这颗生成树中但实际上没被删去的边加回来,当边\((u,v)\)被加回时,\((u,v)\)原本在生成树上的路径就都不是关键航线了(因为\((u,v)\)间已经有了至少两条道路能走)

在加每次操作中涉及的边也是一样

在最初那棵生成树中,每两个点的路径都是唯一的所以每条边都是关键航线,因此在建树时每个点权值赋为1,当它因为有的边被加会而不再关键时就设为0,用线段树维护就行

然后愉快0分

我在求生成树的时候,是和树剖的第一遍dfs一起进行的,但没有单独开vis数组,判断是否访问的时候直接判断if(fa[v]),但1号点(根)的父亲为0,所以就愉快TLE+MLE

改完以后发现10分

忘记pushup这种事肯定不能说出来。。

代码

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cmath>
  5. #include<iomanip>
  6. #include<cstring>
  7. #include<map>
  8. #define R register
  9. #define EN std::puts("")
  10. #define LL long long
  11. inline int read(){
  12. int x=0,y=1;
  13. char c=std::getchar();
  14. while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
  15. while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
  16. return y?x:-x;
  17. }
  18. int n,m;
  19. std::map<int,int>map;
  20. int etot=1,to[200006],nex[200006],fir[30006];
  21. int deleted[200006],ontree[200006];
  22. int fa[30006],deep[30006],size[30006];
  23. int top[30006],dfn[30006],dfscnt,son[30006];
  24. struct tr{
  25. tr *ls,*rs;
  26. int tag,sum;
  27. }dizhi[60007],*root=&dizhi[0];
  28. int tot;
  29. int qc[100006],qx[100006],qy[100006],qtot;
  30. int ans[100006],anstot;
  31. inline void swap(int &x,int &y){x^=y;y^=x;x^=y;}
  32. inline void add(int u,int v){
  33. to[++etot]=v;
  34. nex[etot]=fir[u];fir[u]=etot;
  35. map[u*(n+1)+v]=etot;
  36. }
  37. void dfs1(int u,int fat){
  38. fa[u]=fat;deep[u]=deep[fat]+1;size[u]=1;
  39. for(R int v,i=fir[u];i;i=nex[i])if(!deleted[i]){
  40. v=to[i];
  41. if(fa[v]||v==1) continue;
  42. ontree[i]=1;
  43. dfs1(v,u);size[u]+=size[v];
  44. if(size[v]>size[son[u]]) son[u]=v;
  45. }
  46. }
  47. void dfs2(int u,int topnow){
  48. top[u]=topnow;dfn[u]=++dfscnt;
  49. if(!son[u]) return;
  50. dfs2(son[u],topnow);
  51. for(R int v,i=fir[u];i;i=nex[i])if(ontree[i]){
  52. v=to[i];
  53. if(!dfn[v]) dfs2(v,v);
  54. }
  55. }
  56. void build(tr *tree,int l,int r){
  57. if(l==r) return tree->sum=1,void();
  58. int mid=(l+r)>>1;
  59. tree->ls=&dizhi[++tot];tree->rs=&dizhi[++tot];
  60. build(tree->ls,l,mid);build(tree->rs,mid+1,r);
  61. tree->sum=r-l+1;
  62. }
  63. inline void pushdown(tr *tree){
  64. if(tree->tag){
  65. tree->ls->tag=tree->rs->tag=1;
  66. tree->ls->sum=tree->rs->sum=0;
  67. tree->tag=0;
  68. }
  69. }
  70. void change(tr *tree,int l,int r,int ql,int qr){
  71. if(ql<=l&&r<=qr) return tree->tag=1,tree->sum=0,void();
  72. int mid=(l+r)>>1;
  73. pushdown(tree);
  74. if(ql<=mid) change(tree->ls,l,mid,ql,qr);
  75. if(qr>mid) change(tree->rs,mid+1,r,ql,qr);
  76. tree->sum=tree->ls->sum+tree->rs->sum;
  77. }
  78. int qsum(tr *tree,int l,int r,int ql,int qr){
  79. if(ql<=l&&r<=qr) return tree->sum;
  80. int mid=(l+r)>>1,ret=0;
  81. pushdown(tree);
  82. if(ql<=mid) ret=qsum(tree->ls,l,mid,ql,qr);
  83. if(qr>mid) ret+=qsum(tree->rs,mid+1,r,ql,qr);
  84. return ret;
  85. }
  86. inline void updata(int x,int y){
  87. while(top[x]!=top[y]){
  88. if(deep[top[x]]<deep[top[y]]) swap(x,y);
  89. change(root,1,n,dfn[top[x]],dfn[x]);
  90. x=fa[top[x]];
  91. }
  92. if(dfn[x]>dfn[y]) swap(x,y);
  93. if(dfn[x]!=dfn[y]) change(root,1,n,dfn[x]+1,dfn[y]);
  94. }
  95. inline int sum(int x,int y){
  96. R int ret=0;
  97. while(top[x]!=top[y]){
  98. if(deep[top[x]]<deep[top[y]]) swap(x,y);
  99. ret+=qsum(root,1,n,dfn[top[x]],dfn[x]);
  100. x=fa[top[x]];
  101. }
  102. if(dfn[x]>dfn[y]) swap(x,y);
  103. if(dfn[x]!=dfn[y]) ret+=qsum(root,1,n,dfn[x]+1,dfn[y]);
  104. return ret;
  105. }
  106. int main(){
  107. n=read();m=read();
  108. for(R int x,y,i=1;i<=m;i++){
  109. x=read();y=read();
  110. add(x,y);add(y,x);
  111. }
  112. R int x,y,cc,c=read();while(c!=-1){
  113. x=read();y=read();
  114. qc[++qtot]=c;qx[qtot]=x;qy[qtot]=y;
  115. cc=map[x*(n+1)+y];
  116. if(!c) deleted[cc]=deleted[cc^1]=1;
  117. c=read();
  118. }
  119. dfs1(1,0);dfs2(1,1);
  120. build(root,1,n);
  121. for(R int i=1;i<=n;i++){
  122. for(R int j=fir[i];j;j=nex[j])
  123. if(!ontree[j]&&!ontree[j^1]&&!deleted[j]) updata(i,to[j]);
  124. }
  125. for(R int i=qtot;i;i--){
  126. if(qc[i]) ans[++anstot]=sum(qx[i],qy[i]);
  127. else updata(qx[i],qy[i]);
  128. }
  129. for(R int i=anstot;i;i--) std::printf("%d\n",ans[i]);
  130. return 0;
  131. }

P2542 【[AHOI2005]航线规划】的更多相关文章

  1. 洛谷 P2542 [AHOI2005]航线规划 解题报告

    P2542 [AHOI2005]航线规划 题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系 ...

  2. P2542 [AHOI2005]航线规划 LCT维护双连通分量

    \(\color{#0066ff}{ 题目描述 }\) 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel ...

  3. 洛谷P2542 [AHOI2005]航线规划(LCT,双连通分量,并查集)

    洛谷题目传送门 太弱了不会树剖,觉得LCT好写一些,就上LCT乱搞,当LCT维护双连通分量的练手题好了 正序删边是不好来维护连通性的,于是就像水管局长那样离线处理,逆序完成操作 显然,每个点可以代表一 ...

  4. 洛谷 P2542 [AHOI2005]航线规划(Link-cut-tree)

    题面 洛谷 bzoj 题解 离线处理+LCT 有点像星球大战 我们可以倒着做,断边变成连边 我们可以把边变成一个点 连边时,如果两个点本身不联通,就\(val\)赋为\(1\),并连接这条边 如果,两 ...

  5. 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线

    Code: #include <map> #include <cstdio> #include <algorithm> #include <cstring&g ...

  6. [AHOI2005] 航线规划

    Description 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel ...

  7. AHOI2005航线规划 bzoj1969(LCT缩点)

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  8. 【[AHOI2005]航线规划】

    树剖维护边双 首先我们看到在整个过程中图是保证连通的,于是我们并不需要LCT来维护连通性 而这些询问询问的是两个点之间关键路径的数量,也就是无论怎么走都必须走的数量,显然这就是两点之间的割边的数量 由 ...

  9. [AHOI2005]航线规划——LCT维护边双联通分量

    因为只能支持加入一个边维护边双,所以时光倒流 维护好边双,每次就是提取出(x,y)的链,答案就是链长度-1 具体维护边双的话, void access(int x){ for(reg y=0;x;y= ...

随机推荐

  1. C/C++内存详解

    众所周知,堆和栈是数据结构中的两种数据结构类型,堆是一种具有优先顺序的完全二叉树(或者说是一种优先队列,因为它在一定的优先顺序下满足队列先进先出的特点),排队打饭就是它的典型实例,栈是一种后进先出的数 ...

  2. 正则表达式(JS表格简要总结)

    1. JS中正则表达式定义 JavaScript 中的正则表达式用 RegExp 对象表示. JS中定义正则表达式的两种方法: 方法 示例 RegExp 对象 var pattern = new Re ...

  3. Math.max.apply()用法

    apply的一些其他巧妙用法 Math.max.apply( null, [12,23,34,45] ); //细心的人可能已经察觉到,在我调用apply方法的时候, // 第一个参数是对象(this ...

  4. GeoGebra的一些指令名字

    列举出老师上课提出的一些命令 比较不常见的命令 1.取得函数上一点的坐标值x(A).y(A).z(A) 2.复数指令real() imaginary() 复数中的虚数应该使用Alt+i打出 点的表示指 ...

  5. string 中的getline

    1 getline 读入string库中的字符串 string a; getline(cin,a);  这样的读入要比任何一种读入字符串都有要快 2 char a[N]; cin.getline(a, ...

  6. 01、WireShark——ARP 协议包分析

     1. 什么是ARP ARP(Address Resolution Protocol)协议,即地址解析协议.该协议的功能就是将 IP 地 址解析成 MAC 地址. ARP(Address Resolu ...

  7. JMeter在Mac下的安装

    其实不论操作系统是Windows.Unix(如Mac OS).Linux(如Ubuntu)等,JMeter所需要的基础环境配置都是类似的,本文介绍JMeter for MAC的安装与环境配置. JMe ...

  8. Linux编辑利器-Vim

    在大学时代,Vim 的大名就已如雷贯耳,但由于它陡峭的学习曲线,一直望而却步.等真正开始学习之后,发现并没有想象中的复杂,也没有所谓的瓶颈,只要在实际写代码中强迫自己使用就可以了,无形中就会形成习惯. ...

  9. PHP常量:JSON_UNESCAPED_UNICODE

    函数: json_encode() - 对变量进行 JSON 编码 说明: json_encode ( mixed $value [, int $options = 0 [, int $depth = ...

  10. python3 xlwt,csv学习

    前言 对于抓取一些站点分析然后指纹识别的时候可能用到到它.所以学习下.这里就记录一些最基本的感觉有用的. xlwt 基本创建 demo: #coding=utf- import xlwt yunyin ...