记录编号 56878 评测结果 AAAAA
题目名称 通讯问题 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.001 s
提交时间 2013-04-04 14:42:35 内存使用 0.33 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<deque>
#include<cmath>
#include<algorithm>
using namespace std;
const int SIZEN=101;
//注意:节点下标是1~n
int n;//节点数
bool c[SIZEN][SIZEN]={0};//邻接矩阵
int dfn[SIZEN]={0};//时间戳
int low[SIZEN]={0};//能追溯到的最早时间戳
int index=0;//时间变量
deque<int> st;//栈
bool instack[SIZEN]={0};//是否在栈中
int comsum=0;
int belong[SIZEN]={0};//每个节点在哪个分量内
void Tarjan(int x){//访问x的子树
	if(dfn[x]) return;
	dfn[x]=low[x]=++index;//访问过的点dfn值>0
	st.push_back(x);
	instack[x]=true;
	int i;
	for(i=1;i<=n;i++){
		if(i==x||!c[x][i]) continue;
		if(!dfn[i]){//i节点未被访问
			Tarjan(i);
			low[x]=min(low[x],low[i]);
		}
		else if(instack[i]){//i节点在栈中
			low[x]=min(low[x],dfn[i]);
		}
	}
	if(dfn[x]==low[x]){//x是强连通分量的一个"根"
		comsum++;
		int temp;
		do{
			temp=st.back();
			belong[temp]=comsum;
			instack[temp]=false;
			st.pop_back();
			if(st.empty()||temp==x) break;
		}while(temp!=x);
	}
}
void output(void){
	int i,j;
	printf("%d\n",comsum);
	bool used[SIZEN]={0};
	for(i=1;i<=n;i++){
		if(used[i]) continue;
		for(j=1;j<=n;j++){
			if(belong[j]==belong[i]){
				printf("%d ",j);
				used[j]=true;
			}
		}
		printf("\n");
	}
}
int main(){
	freopen("jdltt.in","r",stdin);
	freopen("jdltt.out","w",stdout);
	scanf("%d",&n);
	int a,b;
	while(!cin.eof()){
		cin>>a>>b;
		c[a][b]=1;
	}
	for(int i=1;i<=n;i++){
		Tarjan(i);
	}
	output();
	return 0;
}