连通性相关

无向图的边双连通分量

求桥

变量

  • int dfn[i]\texttt{int dfn[i]}:点 ii 的时间戳。
  • int low[i]\texttt{int low[i]}:点 ii 的追溯值。
  • int num\texttt{int num}:统计时间戳的中间变量。
  • bool bri[i]\texttt{bool bri[i]}:边 ii 是否为桥。

函数

  • void tarjan(int x,int in)\texttt{void tarjan(int x,int in)}:求从点 xx 开始,入边为 inin 时的桥。

代码

int dfn[N],low[N],num;
bool bri[M<<1];
void tarjan(int x,int in){
	dfn[x]=low[x]=++num;
	for(int i=head[x];i;i=nxt[i]){
		int y=ver[i];
		if(!dfn[y]){
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x])bri[i]=bri[i^1]=1;
		}
		else if(i!=(in^1))low[x]=min(low[x],dfn[y]);
	}
}

缩点

变量

  • int dfn[i]\texttt{int dfn[i]}:点 ii 的时间戳。
  • int low[i]\texttt{int low[i]}:点 ii 的追溯值。
  • int num\texttt{int num}:统计时间戳的中间变量。
  • bool bri[i]\texttt{bool bri[i]}:边 ii 是否为桥。
  • int col[i]\texttt{int col[i]}:点 ii 所属的边双连通分量。
  • int dcc\texttt{int dcc}:边双个数。

函数

  • void tarjan(int x,int in)\texttt{void tarjan(int x,int in)}:求从点 xx 开始,入边为 inin 时的桥。
  • void dfs(int x)\texttt{void dfs(int x)}:求出删去桥后形成的连通块。

代码

int dfn[N],low[N],num;
bool bri[M<<1];
int col[N],dcc;
void tarjan(int x,int in){
	dfn[x]=low[x]=++num;
	for(int i=G1.head[x];i;i=G1.nxt[i]){
		int y=G1.ver[i];
		if(!dfn[y]){
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x]){
				bri[i]=bri[i^1]=1;
			}
		}
		else if(i!=(in^1))low[x]=min(low[x],dfn[y]);
	}
}
void dfs(int x){
	col[x]=dcc;
	s[dcc]+=a[x];
	for(int i=G1.head[x];i;i=G1.nxt[i]){
		int y=G1.ver[i];
		if(col[y]||bri[i])continue;
		dfs(y);
	}
}

无向图的点双连通分量

求割点

变量

  • int dfn[i]\texttt{int dfn[i]}:点 ii 的时间戳。
  • int low[i]\texttt{int low[i]}:点 ii 的追溯值。
  • int num\texttt{int num}:统计时间戳的中间变量。
  • int root\texttt{int root}:图的根。
  • bool cut[i]\texttt{bool cut[i]}:点 ii 是否为割点。

函数

  • void tarjan(int x)\texttt{void tarjan(int x)}:求从点 xx 开始的割点。

代码

int num,root,dfn[N],low[N];
bool cut[N];
void tarjan(int x){
	dfn[x]=low[x]=++num;
	int flag=0;
	for(int i=head[x];i;i=nxt[i]){
		int y=ver[i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(dfn[x]<=low[y]){
				flag++;
				if(x!=root||flag>1)
					cut[x]=1;
			}
		}
		else
			low[x]=min(low[x],dfn[y]);
	} 
}

圆方树

变量

  • int dfn[i]\texttt{int dfn[i]}:点 ii 的时间戳。
  • int low[i]\texttt{int low[i]}:点 ii 的追溯值。
  • int num\texttt{int num}:统计时间戳的中间变量。
  • bool cut[i]\texttt{bool cut[i]}:点 ii 是否为割点。
  • int rt\texttt{int rt}:图的根。
  • int sta[i]\texttt{int sta[i]}:栈内第 ii 个元素。
  • int top\texttt{int top}:栈顶。
  • int dcc\texttt{int dcc}:圆方树总点数,初始值为 nn

函数

  • void tarjan(int x)\texttt{void tarjan(int x)}:从点 xx 开始,划分圆方树。

代码

int dfn[N],low[N],num,cut[N],rt,sta[N],top,dcc;
void tarjan(int x){
	dfn[x]=low[x]=++num;
	sta[++top]=x;
	int flag=0;
	for(int i=G1.head[x];i;i=G1.nxt[i]){
		int y=G1.ver[i],z;
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(dfn[x]<=low[y]){
				dcc++;flag++;
				do{
					z=sta[top--];
					G2.add(dcc,z);G2.add(z,dcc);
				}while(z!=y);
				G2.add(dcc,x);G2.add(x,dcc);
				if(x!=rt||flag>1)cut[x]=1;
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}

有向图的强连通分量

缩点

变量

  • int dfn[i]\texttt{int dfn[i]}:点 ii 的时间戳。
  • int low[i]\texttt{int low[i]}:点 ii 的追溯值。
  • int num\texttt{int num}:统计时间戳的中间变量。
  • int scc\texttt{int scc}:缩点后总点数,初始值为 nn
  • bool col[i]\texttt{bool col[i]}:点 ii 所在的 sccscc 的编号。
  • int sta[i]\texttt{int sta[i]}:栈内第 ii 个元素。
  • int top\texttt{int top}:栈顶。
  • int ins[i]\texttt{int ins[i]}:点 ii 是否在栈内。

函数

  • void tarjan(int x)\texttt{void tarjan(int x)}:从点 xx 开始,划分强联通分量。
  • void init()\texttt{void init()}:缩点建 DAG\text{DAG}

代码

int dfn[N],low[N],num,scc,col[N];
int sta[N],top,ins[N];
void tarjan(int x){
	dfn[x]=low[x]=++num;
	ins[sta[++top]=x]=1;
	for(int i=G1.head[x];i;i=G1.nxt[i]){
		int y=G1.ver[i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(ins[y])low[x]=min(low[x],dfn[y]); 
	}
	if(dfn[x]==low[x]){
		int y;scc++;
		do{
			ins[y=sta[top--]]=0;
			col[y]=scc;
		}while(x!=y);
	}
}
void init(){
	for(int x=1;x<=n;x++)
		for(int i=G1.head[x];i;i=G1.nxt[i]){
			int y=G1.ver[i];
			if(col[x]!=col[y])
				G2.add(col[x],col[y]);
		}
}
posted @ 2023-08-29 22:07  luckydrawbox  阅读(12)  评论(0)    收藏  举报  来源