Tarjan模板大全

点双连通分量

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int n,m,t,ans;
int dfn[100001],low[100001],sum,in;
vector<int>gcc[100001],g[100001];
stack<int>s;
void tarjan(int u,int fa) {
	dfn[u]=low[u]=++in;
	if(fa==-1&&g[u].size()==0){
		gcc[u].push_back(++sum);
		return;
	}
	s.push(u);
	for(int i=0; i<g[u].size(); i++) {
		int v=g[u][i];
		if(v==fa)continue;
		if(!dfn[v]) {
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]){
				sum++;
				int d;
				do{
					d=s.top();
					s.pop();
					gcc[d].push_back(sum);
				}while(d!=v);
				gcc[u].push_back(sum);
			}
		} else {
			low[u]=min(low[u],dfn[v]);
		}
	}
}
int main() {
	cin>>n>>m;
	while(m--) {
		int x,y;
		cin>>x>>y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	for(int i=1; i<=n; i++) {
		if(!dfn[i])tarjan(i,-1);
	}
	return 0;
}

边双连通分量

#include<iostream>
#include<cstring>
using namespace std;
struct ed {
	int to,next;
} a[1000001];
int head[300001];
int n,m,q,t,ans;
int dfn[300001],low[300001],scc[300001],cnt,in;
bool vis[1000001];
void tarjan(int u,int fa) {
	dfn[u]=low[u]=++in;
	for(int i=head[u]; i!=-1; i=a[i].next) {
		if((i^1)==fa)continue;
		int v=a[i].to;
		if(!dfn[v]) {
			tarjan(v,i);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u]){
				vis[i]=vis[i^1]=true;
			}
		} else {
			low[u]=min(low[u],dfn[v]);
		}
	}
}
void dfs(int u) {
	scc[u]=cnt;
	for(int i=head[u]; i!=-1; i=a[i].next) {
		int v=a[i].to;
		if(!scc[v]&&!vis[i])dfs(v);
	}
}
void add(int u,int v) {
	a[t].to=v;
	a[t].next=head[u];
	head[u]=t++;
}
int main() {
	cin>>n>>m>>q;
	memset(head,-1,sizeof(head));
	while(m--) {
		int x,y;
		cin>>x>>y;
		add(x,y),add(y,x);
	}
	for(int i=1; i<=n; i++) {
		if(!dfn[i])tarjan(i,-1);
	}
	for(int i=1; i<=n; i++) {
		cnt++;
		if(!scc[i])dfs(i);
	}
	return 0;
}

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
struct ed {
	int to,next;
} a[200001];//edge*2
int head[100001];
int n,m,in,dfn[100001],low[100001];
bool vis[100001];
void tarjan(int u,int fa) {
	dfn[u]=low[u]=++in;
	for(int i=head[u]; i!=-1; i=a[i].next) {
		if((i^1)==fa)continue;
		int v=a[i].to; 
		if(!dfn[v]) {
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])vis[i]=vis[i^1]=true;
		} else {
			low[u]=min(low[u],dfn[v]);
		}
	}
}
int main() {
	cin>>n>>m;
	while(m--) {
		int u,v;
		cin>>u>>v;
		add(u,v),add(v,u);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i])tarjan(i,-1);
	}
	return 0;
}

割点

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
bool vis[10001];
int n,m,in,sum,dfn[10001],low[10001],cnt[10001];
vector<int>g[10001];
void tarjan(int u,int fa) {
	dfn[u]=low[u]=++in;
	int c=0;
	for(int i=0; i<g[u].size(); i++) {
		int v=g[u][i];
		if(v==fa)continue;
		if(!dfn[v]) {
			c++;
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])iscp=true;
		} else {
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(fa==-1&&c<=1)iscp[u]=false;
}
int main() {
	cin>>n>>m;
	while(m--) {
		int u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i=1; i<=n; i++) {
		if(!dfn[i])tarjan(i,-1);
	}
	return 0;
}

强连通分量

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
vector<int> g[10001];
int n,m,x,y,dfn[10001],low[10001],scc[10001],cnt,index;
stack<int> st;
void tarjan(int u){
	dfn[u]=low[u]=++index;
	st.push(u);
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else{
			if(!scc[v])low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		cnt++;
		int v;
		do{
			v=st.top();
			st.pop();
			scc[v]=cnt;
		}while(u!=v);
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		g[x].push_back(y);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i])tarjan(i);
	}
	return 0;
}

posted @ 2020-08-27 19:43  ezlmr  阅读(136)  评论(0编辑  收藏  举报