title

Tarjan

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N = 110,M = 110;
struct edge{
	int to,nxt;
}e[M];			//边的集合
int vis[N];		//标记是否在栈中
int stk[N];		//维护栈 
int belong[N];	//各顶点属于哪个强连通分量
int dfn[N];		//时间戳
int low[N];		//u或u的子树能够追溯到的最早的栈中节点的序号(时间戳)
int cnt;		//序号(dfn)
int top;		//栈顶
int tcnt;		//强连通分量计数器
int n,m,head[N],tot;
inline int read(){
	int f=0,x=0;
	char ch=getchar();
	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
inline void add(int u,int v){
	e[++tot].to=v;
	e[tot].nxt=head[u];
	head[u]=tot;
}
inline void tarjan(int u){
	dfn[u]=low[u]=++cnt;
	vis[u]=true;
	stk[++top]=u;
	 
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	
	if(dfn[u]==low[u]){
		tcnt++;
		int v;
		do{
			v=stk[top--];
			vis[v]=false;
			belong[v]=tcnt;
		}while(u!=v);
	}
}
inline void solve(){
	for(int i=1;i<=n;++i)
		if(!dfn[i])
			tarjan(i);
}
signed main(){
	n=read();m=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read();
		add(u,v);
	}
	solve();
	for(int i=1;i<=n;++i)
		printf("%d ",belong[i]);
	return 0;
}
/*
6 8
1 2
1 3
2 4
3 4
3 5
4 1
4 6
5 6
ans:3 3 3 3 2 1
*/
posted @ 2018-09-10 01:05  Horrigue_JyowYang  阅读(77)  评论(0编辑  收藏  举报