【强连通】【模板】Tarjan算法求连通图、割点、桥 + 【例题】

11 篇文章 0 订阅
8 篇文章 0 订阅

Tarjan算法求连通图(代码含所需变量、初始化步骤):

#define MAXN 100000+5
//struct edge{
//	int to;
//	//int val;        //若边有权值所需要的元素
//};
//int next[MAXN]; 
vector<int> G[MAXN];
int dfn[MAXN],low[MAXN];
bool instack[MAXN];
stack<int> s;				
int timing;				//时间戳 
int color[MAXN];		//代表当前结点所属第几个scc 
int colorcnt[MAXN];		//代表第某个scc有几个结点 
int cnt;				//scc个数 
int V,E;				

void init()
{
	for(int i=0;i<=V;i++)
		G[i].clear();
	while(!s.empty())
		s.pop();
	mem(dfn,0);
	mem(color,0);
	mem(colorcnt,0);
	mem(instack,false);
	mem(low,0);
	timing=cnt=0;
}

void tarjan(int u)
{
	timing++;
	dfn[u]=low[u]=timing;
	s.push(u);
	instack[u]=true;
	for(int i=0;i<G[u].size();i++)
	{
		//int v=next[u];
		int v=G[u][i];
		if(dfn[v]==0)
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(instack[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	
	if(low[u]==dfn[u])
	{
		cnt++;
		int temp;
		do
		{
			//记录每个点属于哪个scc
			temp=s.top();
			s.pop();
			instack[temp]=false;
			color[temp]=cnt;
			colorcnt[cnt]++;	
		}while(u!=temp);	
	}
}

Tarjan算法的调用:

int main()
{
	while(cin >> V >> E && V+E)
	{
		init();
		int a,b;
		for(int i=0;i<E;i++)
		{
			cin >> a >> b;
			G[a].push_back(b);
		}
		for(int i=1;i<=V;i++)
			if(dfn[i]==0)
				tarjan(i);
		cout << cnt << endl;
	}
	return 0;
}

Tarjan算法求割点与求桥是基于无向图的! 

Tarjan算法求割点(割点:去掉一个关键点、使得连通图不连通):

#define MAXN 105
//struct edge{
//	int to;
//	//int val;		//如果有权值可以添加 
//};
//int next[MAXN]; 
vector<int> G[MAXN];
int dfn[MAXN],low[MAXN];
bool instack[MAXN];
set<int> ans;		//存储割点 
stack<int> s;				
int timing;				//时间戳 
int color[MAXN];		//代表当前结点所属第几个scc 
int colornum[MAXN];		//代表第某个scc有几个结点 
int cnt;				//scc个数 
int V,E;				 

void init()
{
	for(int i=0;i<=V;i++)
		G[i].clear();
	ans.clear();
	mem(dfn,0);
	mem(color,0);
	mem(colornum,0);
	mem(instack,false);
	mem(low,0);
	timing=cnt=0;
}

割点 
void tarjan_Point(int u,int rt)
{
	++timing;
	low[u]=dfn[u]=timing;
	int child=0; 
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(dfn[v]==0)
		{
			child++;
			tarjan_Point(v,rt);
			low[u]=min(low[u],low[v]);
			if(u!=rt && low[v]>=dfn[u]){
				ans.insert(u);
			}
		}
		low[u]=min(low[u],dfn[v]);
	}		
	if(child>=2&&u==rt){
		ans.insert(u);
	}
}

求割点的调用:

int main()
{
    cin >> V >> E;
    for(int i=0;i<E;i++){
        int a,b;
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
	for(int i=1;i<=V;i++)
		if(dfn[i]==0)
			tarjan_Point(i,i);
	cout << ans.size() << endl;
	return 0;
}

Tarjan算法求桥(桥:在连通图中去掉一个边、使得连通图不连通)

struct edge{
	int from,to;
};
edge qiao[MAXN];
void addpath(int a,int b){
	qiao[top].from=min(a,b);
	qiao[top++].to=max(a,b);
}

void tarjan_Edge(int u,int fa) {
    dfn[u]=low[u]=++timing;
    for(int i=0; i<G[u].size(); i++) {
        int v=G[u][i];
        if(v==fa)
        	continue;
        if(!dfn[v]) {
            tarjan_Edge(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])
				addpath(u,v);
        }
     	else if(fa!=u){
     		low[u]=min(low[u],dfn[v]);
		 }
    }
}

与割点的调用一模一样、不再贴出代码……


Tarjan算法相关题目:

HDU 1269 迷宫城堡 【传送门】(模板题)

UVA 315 Network 【传送门】(模板题)

UVA 796 Critical Link 【传送门】 (模板题)

洛谷 P3388 【传送门】 (模板题)

POJ 3180 The Cow Prom 【传送门】(模板题)

POJ 1236 Network of Schools 【传送门】

POJ 2186 Popular cows 【传送门】

未完待续……

POJ 2553 The bottom of a Graph

POJ 3177 Redundant Paths

POJ 3352 Road Construction

HDU 5934 Bomb

HDU 4612 Warm up

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值