codevs1332 Tarjan的写法

上篇文章,记录了用Kosaraju算法写这道模板题,为了学习强连通分量,又去学习下Tarjan算法。先看书,嗯,感觉看文字看完了,讲的啥玩意为啥呀?不懂。于是还是先百度一下吧。(强连通分量,Tarjan算法,点击百度一下)啊,这篇文章不错,讲了一些,还给了模板,虽然背后的原理还是没懂,但大致算法步骤知道了。

还给了模板,想一想,既然模板题,就应该用模板过题。对,有道理。ctrl+c,ctrl+v,魔改一下,自己加上染色数组,加上注释。样例没问题,交一发?交。我靠,一发AC  下面是代码,hahaha。

/*
 *looooop
 * Do not go gentle into that good night
 *				              -Dylan Thomas
 */

#include <iostream>  
#include <stdio.h>  
#include <string.h>  
#include <stack>  
#include <queue>  
#include <map>  
#include <set>  
#include <vector>  
#include <math.h>  
#include <bitset>  
#include <algorithm>  
#include <climits>  
using namespace std;

#define lson 2*i  
#define rson 2*i+1  
#define LS l,mid,lson  
#define RS mid+1,r,rson  
#define UP(i,x,y) for(i=x;i<=y;i++)  
#define DOWN(i,x,y) for(i=x;i>=y;i--)  
#define MEM(a,x) memset(a,x,sizeof(a))  
#define W(a) while(a)  
#define gcd(a,b) __gcd(a,b)  
#define LL long long  
#define N 1000005  
#define MOD 1000000007  
#define INF 0x3f3f3f3f  
#define EXP 1e-8  
#define lowbit(x) (x&-x)
#define MAX 50005
vector<int>G[MAX];
int dfn[MAX];		//Tarjan算法的核心数组,dfn[v]表示顶点被访问的时间
int low[MAX];		//low[v]是与顶点v邻接的未删除的顶点u的low[u]和low[v]的最小值(low[v]初始化为dfn[v])
int belong[MAX];	//表示顶点染色集合,belong[i]表示i的颜色,即i所属的强连通分量
int sum[MAX];		//染色数的集合,sum[i]表示第i种颜色的顶点数量,即连通分量所包含的顶点数量
int vis[MAX];
int cnt;
int tot;			//染色数,强连通分量的数量
int n,m;
int a,b,t;
stack<int>ST;		//Tarjan所维护dfn,low使用的栈

void Tarjan(int st){
	dfn[st] = low[st] = ++tot;	//初始化dfn,low 
	vis[st] = 1;				//vis = 1表示在栈中
	ST.push(st);
	for(int i=0; i < G[st].size(); i++){	//遍历所有相连的边
		int v = G[st][i];
		if(!dfn[v]){	//还未访问
			Tarjan(v);
			low[st] = min(low[st],low[v]);
		}
		else if(vis[v]){	//被访问,但还在栈中
			low[st] = min(low[st],dfn[v]);
		}
	}
	if(low[st] == dfn[st]){		//dfn == low表示找到了一个强连通分量子树的根
		int x;
		++cnt;			//染色的色彩,
		while(1){		//从连通树中一个个的取分量 
			x = ST.top();
			ST.pop();
			vis[x] = 0;
			belong[x] = cnt;
			sum[cnt]++;
			if(x == st)	break;
		}
	}
}
void Solve(){
	tot = 0;
	cnt = 0;
	MEM(dfn,0);
	MEM(low,0);
	MEM(vis,0);
	while(!ST.empty())	ST.pop();
	for(int i=1; i <=n; i++){
		if(dfn[i] == 0)	Tarjan(i);
	}
}
int main(int argc,char *argv[]){
	scanf("%d%d",&n,&m);
	for(int i = 0; i < m; i++){
		scanf("%d%d%d",&a,&b,&t);
		if(t==1){
			G[a].push_back(b);
		}
		else{
			G[a].push_back(b);
			G[b].push_back(a);
		}
	}
	Solve();
	int temp = 1;
	for(int i = 1; i <= tot; i++){
		if(sum[i] >= sum[temp])	temp = i;
	}
	printf("%d\n",sum[temp]);
	for(int i = 1; i <= n; i++){
		if(belong[i] == temp)
			printf("%d ",i);
	}
	printf("\n");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SuperBvs/article/details/83930392