关于Tarjan(2)

     Tarjan有第二个神奇的用法,求强连通分量!!!!!!!!!!!!!!!!!!!
同样利用了dfn:dfs序,low:能回到的最早祖先的dfn;

废话少说 上板子

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>//栈的stl需要头文件 
#include<set>
using namespace std;
sstack<int>s;//定义该栈 
int n,m,a,b;
struct data{
	int to,nxt;
}edge[200000*2+1];
int sum,tot,len,tag,sig;
bool vis[100001];
int low[100001],dfn[100001],head[100001];
bool ans[100001];
void add(int from,int to){
	edge[++sum].nxt=head[from];
	head[from]=sum;
	edge[sum].to=to;
}
int comp(const data1&a,const data1&b){return a.st<b.st;}
void Tarjan(int now){
	s.push(now);//压入栈 
	vis[now]=true;//表示在栈中 
	dfn[now]=low[now]=++tot;//时间戳,low值初始化 
	for(int i=head[now];i;i=edge[i].nxt){//同样链式前向星 
		int to=edge[i].to;
		if(!dfn[to]){
			Tarjan(to);
			low[now]=min(low[to],low[now]);//更新low 
		}
		else if(vis[to])low[now]=min(low[now],dfn[to]);//在栈中,需更新 
	}
	if(dfn[now]==low[now]){
		int u=-1;
		int ll=answer[++tag].l=len+1;//对输出值排序 
		while(u!=now){
			u=s.top();
			vis[u]=false;//表示已经出栈 
			ans[++len]=u;
			s.pop();//同上 
		}
		int rr=answer[tag].r=len;
		sort(ans+ll,ans+rr+1);//这里只是对输出强连通分量个数及其元素起作用 
		answer[tag].st=ans[ll];
	}
}
void print(){
	printf("%d\n",tag);
	sort(answer+1,answer+tag+1,comp);
	for(int i=1;i<=tag;++i)
	{
		for(int j=answer[i].l;j<=answer[i].r;++j)
		printf("%d ",ans[j]);
		printf("\n");
	}
	return;
}
int main(){
	scanf("%d",&n);
	while(scanf("%d%d",&a,&b)!=EOF)add(a,b);
	for(int i=1;i<=n;++i)
	if(!dfn[i])Tarjan(i);//若有一部分不与其他相连接 
	print();
	return 0;
}


posted @ 2017-01-23 10:26  QYP_2002  阅读(92)  评论(0编辑  收藏  举报