[差分][倍增lca][tarjan] Jzoj P3325 压力
Posted comfortable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[差分][倍增lca][tarjan] Jzoj P3325 压力相关的知识,希望对你有一定的参考价值。
题解
- 题目大意:给出一个 N 个点,M 条边的连通图,和 M 个点对。询问删掉每个点会使 M 个点对中的几个不连通
- 其实就类似于求路径上有多少个割点
- 首先,可以tarjan求点双分量,然后建新点,也就是缩点
- 最后得到一颗树
- 然后就在树上求两点的lca
- 最后就是差分了
- 那么怎么做?
- 将x,y点++,lca--,lca的父亲--
- 那么怎么处理在路径上的割点呢?
- 在倍增时,记录对于新建点的父亲
- 那新建点也就是缩点后的点与父亲只有一条路径
- 那么就可以将父亲的差分+当前点的差分,一步一步将树向上加
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<vector> 8 using namespace std; 9 struct edge {int to,from; }e[200010*2],c[200010*2]; 10 int n,m,q,dis,tot,cnt,num,cnt1,cnt2,head[200010],last[200010],dfn[100010],low[100010],k[100010],sh[200010],f[200010][21],dep[200010],d[200010]; 11 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; } 12 void insert1(int x,int y) { c[++cnt2].to=y; c[cnt2].from=last[x]; last[x]=cnt2; } 13 void tarjan(int x) 14 { 15 dfn[x]=low[x]=++cnt1; k[++num]=x; 16 for (int i=head[x];i;i=e[i].from) 17 { 18 int v=e[i].to; 19 if (dfn[v]==-1) 20 { 21 tarjan(v); 22 low[x]=min(low[x],low[v]); 23 if (low[v]>=dfn[x]) 24 { 25 tot++; 26 int j; 27 do 28 { 29 j=k[num--]; 30 insert1(tot,j); insert1(j,tot); 31 } 32 while (j!=v); 33 insert1(x,tot);insert1(tot,x); 34 } 35 } 36 else low[x]=min(low[x],dfn[v]); 37 } 38 } 39 void dfs(int x,int fa) 40 { 41 sh[sh[0]++]=x; f[x][0]=fa; 42 for (int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1]; 43 for (int i=last[x];i;i=c[i].from) 44 { 45 int v=c[i].to; 46 if (v==fa) continue; 47 dep[v]=dep[x]+1; 48 dfs(v,x); 49 } 50 } 51 int lca(int x,int y) 52 { 53 if (dep[x]>dep[y]) swap(x,y); 54 for (int i=20;i>=0;i--) 55 if (dep[f[y][i]]>=dep[x]) 56 y=f[y][i]; 57 if (x==y) return x; 58 for (int i=20;i>=0;i--) 59 if (f[x][i]!=f[y][i]) 60 x=f[x][i],y=f[y][i]; 61 return f[x][0]; 62 } 63 int main() 64 { 65 scanf("%d%d%d",&n,&m,&q); 66 tot=n; 67 for (int i=1;i<=m;i++) 68 { 69 int u,v; 70 scanf("%d%d",&u,&v); 71 insert(u,v); insert(v,u); 72 } 73 memset(dfn,-1,sizeof(dfn)); 74 tarjan(1); 75 dep[1]=1; dfs(1,0); 76 for (int i=1;i<=q;i++) 77 { 78 int x,y; 79 scanf("%d%d",&x,&y); 80 dis=lca(x,y); 81 d[x]++; d[y]++; d[dis]--; d[f[dis][0]]--; 82 } 83 for (int i=tot;i>=1;i--) 84 { 85 int now=sh[i]; 86 d[f[now][0]]+=d[now]; 87 } 88 for (int i=1;i<=n;i++) printf("%d ",d[i]); 89 return 0; 90 }
以上是关于[差分][倍增lca][tarjan] Jzoj P3325 压力的主要内容,如果未能解决你的问题,请参考以下文章