消息的传递 (tarjan)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38772011/article/details/90109829

http://lpoj.cn/problemdetail?problemID=104

tarjan 缩点 求入度为0的联通分量

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
int n,a;
int ans,num;
int tnt,head[MAXN],to[MAXN],next1[MAXN];
int low[MAXN];//最早祖先的标号
int mmm[MAXN]; //连通图编号 
int dfn[MAXN]; 
int cnt,vis[MAXN],index1[MAXN];
void add(int a,int b) {
	tnt++; 
	to[tnt]=b;
	next1[tnt]=head[a];
	head[a]=tnt;
	return ;
}
stack<int>s;
void Tarjan(int u) {
	dfn[u]=low[u]=++cnt;
	s.push(u);
	vis[u]=1;
	for(int e=head[u]; e; e=next1[e]) {
		if(!dfn[to[e]]) {
			Tarjan(to[e]);
			low[u]=min(low[u],low[to[e]]); //更新祖先 
		} else if(vis[to[e]]) low[u]=min(low[u],dfn[to[e]]);
	}
	if(low[u]==dfn[u]) {
		num++;
		while(!s.empty() && s.top()!=u)
		{
			mmm[s.top()]=num;
			vis[s.top()]=0;
			s.pop();
		 } 
		if(!s.empty())
		{
			mmm[s.top()]=num;
			vis[s.top()]=0;
			s.pop();
		}
	}
	return ;
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++) {
			scanf("%d",&a);
			if(a)
				add(i,j);
		}
	for(int i=1; i<=n; i++)
		if(!dfn[i])
			Tarjan(i);
	for(int u=1; u<=n; u++)
		for(int e=head[u]; e; e=next1[e])
			if(mmm[u]!=mmm[to[e]])
				index1[mmm[to[e]]]++;
	for(int i=1; i<=num; i++)
		if(!index1[i])
			ans++;
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/weixin_38772011/article/details/90109829