压力
来源:互联网 发布:g71循环编程实例 编辑:程序博客网 时间:2024/06/02 13:51
题目大意
有一张联通无向图,还有许多点对,你需要输出每个点是多少点对的必经点(即如果点对为u,v,那么如果u到v无论如何都要经过x,那么x是该点对的必经点)
建一颗富榄树
富爷:这个叫割点树,是我命名的
那么我们暂且称他为富榄树
富榄树是什么?我们清楚,如果是一张有向图,如果一提到必经点,我们脑海中可以跳出来一个东西——抖M树(dominator tree),它对每个节点保留了一个最近支配点,然后让每个点的父亲为其最近支配点建出了一棵树,这个棵树叫抖M树。假设根节点为1,那么对于任意节点i,只有1到i在抖M树的树路径上的点删去后会对1和i的连通性造成影响。
富榄树的思想类似,首先对无向图建出dfs树,然后每个点保留其最近割点。那你要问啦,无向图割点是怎么定义的?无向图的割点只有相对而言,x对于y是割点,则定义z为x的一个儿子且z为y祖先,那么如果low[z]>=dfn[x],则x是y的一个割点。每个点都可能有很多割点,只需要保留最近那个即可。
具体的,我们盗用一下抖M树的数组名,用idom[i]表示i的最近割点,那么j是i的父亲,如果low[i]>=dfn[j](即j是i的割点),idom[i]=j,否则idom[i]=idom[j](因为j的割点一定是i的割点)。然后求出了idom,我们就可以建出抖M富榄树啦!(鼓掌熊
与抖M树类似,富榄树更加强大的是,他不需要起点固定。
离线大法好
对于路线u到v,我们求出其在dfs树上的lca w。找到一个在dfs树上深度最小的x满足其在富榄树上是u的祖先且其在dfs树上深度大于w,同样对于v找到一个y。那么我们知道,在富榄树上,u到x的树路径上的所有点以及v到y的树路径上的所有点被删去后u和v的连通性将受到影响,所以这些点的ans得加一。w删去后会不会对u和v的连通性有影响呢?如果w是x或y其中一个的割点,则ans[w]++,否则显然删去w后从u出发到x然后跳到上面去再飞下来到y再走到v是合法的。
然后现在就变成若干操作每个操作形如把u到v路径上的点ans都加一。这个显然可以离线做,即我们弄一个cnt,在u时影响+1,到了v时要消除影响。
貌似要特判u和v在一条链上的情况,反正我特判了,详见代码。
有一个有趣的东西是,我们用tarjan求low和dfn顺便建dfs树,同时我们可以用tarjan求lca,%%%tarjan。
#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=100000+10,maxm=200000*2+10,maxp=200000+10;struct dong{ int u,v,w;};dong ask[maxp];int h4[maxn],h[maxn],d[maxn],go[maxm],next[maxm],dfn[maxn],nfd[maxn],low[maxn],fa[maxn],fath[maxn],fat[maxn][20],ans[maxn];int h1[maxm],n1[maxm],g1[maxm],h2[maxm],n2[maxm],g2[maxm],h3[maxm],n3[maxm],g3[maxm];bool bz[maxn],pp[maxm],ppp[maxn];int i,j,k,l,t,n,m,p,tot,t1,t2,t3,top,cnt,u,v,w,x,y,limit;void add(int x,int y){ go[++tot]=y; next[tot]=h[x]; h[x]=tot;}void add1(int x,int y){ g1[++t1]=y; n1[t1]=h1[x]; h1[x]=t1;}void add2(int x,int y){ g2[++t2]=y; n2[t2]=h2[x]; h2[x]=t2;}void add3(int x,int y){ g3[++t3]=y; n3[t3]=h3[x]; h3[x]=t3;}int getfa(int x){ return fa[x]?fa[x]=getfa(fa[x]):x;}void tarjan(int x){ low[x]=dfn[x]=++top; nfd[top]=x; int t=h[x],i,y,z; while (t){ if (!dfn[go[t]]){ d[go[t]]=d[x]+1; tarjan(go[t]); fa[go[t]]=x; fath[go[t]]=x; low[x]=min(low[x],low[go[t]]); } else low[x]=min(low[x],dfn[go[t]]); t=next[t]; } t=h2[x]; while (t){ i=g2[t]; if (x==ask[i].u) swap(ask[i].u,ask[i].v); y=ask[i].u; if (bz[y]){ y=getfa(y); ask[i].w=y; } t=n2[t]; } bz[x]=1;}void solve(int x){ bz[x]=1; int t=h[x]; while (t){ if (d[go[t]]==d[x]+1&&!bz[go[t]]){ if (low[go[t]]>=dfn[x]) fat[go[t]][0]=x;else fat[go[t]][0]=fat[x][0]; solve(go[t]); } t=next[t]; }}int dfs(int x){ int t,y,cnt=0; t=h1[x]; while (t){ y=g1[t]; cnt+=dfs(y); t=n1[t]; } t=h3[x]; while (t){ y=g3[t]; cnt++; h4[y]++; t=n3[t]; } ans[x]+=cnt; cnt-=h4[x]; h4[x]=0; return cnt;}int main(){ scanf("%d%d%d",&n,&m,&p); fo(i,1,m){ scanf("%d%d",&j,&k); add(j,k); add(k,j); } fo(i,1,p){ scanf("%d%d",&j,&k); ask[i].u=j;ask[i].v=k; add2(j,i); add2(k,i); } d[1]=1; tarjan(1); low[1]=0; fo(i,1,n) bz[i]=0; solve(1); fo(i,2,n) add1(fat[i][0],i); fo(j,1,floor(log(n)/log(2))) fo(i,1,n) fat[i][j]=fat[fat[i][j-1]][j-1]; fo(i,1,p){ u=ask[i].u;v=ask[i].v;w=ask[i].w; if (v==w) swap(u,v); if (u==w){ y=v; fd(j,floor(log(n)/log(2)),0) if (d[fat[y][j]]>d[w]) y=fat[y][j]; add3(v,y); ans[u]++; continue; } x=u; fd(j,floor(log(n)/log(2)),0) if (d[fat[x][j]]>d[w]) x=fat[x][j]; y=v; fd(j,floor(log(n)/log(2)),0) if (d[fat[y][j]]>d[w]) y=fat[y][j]; if (fat[x][0]==w||fat[y][0]==w) ans[w]++; add3(u,x); add3(v,y); } t=dfs(1); fo(i,1,n) printf("%d\n",ans[i]);}
- 压力
- 压力
- 压力
- 压力
- 压力
- 压力
- 压力
- 压力
- 压力
- 压力...
- 压力
- 压力
- 压力,压力,压力真的来了
- 压力?动力?
- 顶住压力~~~
- 缓解压力
- 压力测试
- 压力测试
- 欢迎使用CSDN-markdown编辑器
- mac系统下使用sapjco导致maven中依赖的jar包无法引入
- 左旋转字符串
- java多线程学习
- php 7.0 特性
- 压力
- Symbolic link and hard link的区别(linux)
- AWS vpc 安全组问题
- android 小工具集合
- MyFirst
- 夯实C基础,起步打扎实
- 设置php的环境变量 php: command not found
- 认识OC
- ❤️C++语言特点: