81分求助
查看原帖
81分求助
205782
R浩轩泽Anmicius楼主2020/7/21 12:01
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define N 205
#define signed register int
int n,num,head[N],dfn[N],lows[N],sta[N],sta_num[N],visn,stan,ans;
bool vis[N],in[N];
stack<int>s;
struct Edge{
	int to;
	int next;
}edge[N*N];
inline void AddEdge(int x,int y)
{
	edge[++num].to=y;
	edge[num].next=head[x];
	head[x]=num;
}
inline void Tarjan(int u)
{
	dfn[u]=lows[u]=++visn;//时间戳 
	s.push(u);vis[u]=true;
	for(signed i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(!vis[v])
		{
			Tarjan(v);
			lows[u]=min(lows[u],lows[v]);
		}
		else if(!sta[v])//访问过而不在栈中 
		lows[u]=min(lows[u],dfn[v]);//形成环 
	}
	if(dfn[u]==lows[u])
	{
		sta[u]=++stan;//染色序号
		while(s.top()!=u)
		{
			sta[s.top()]=stan;//染色一致 
			s.pop();
		}
		s.pop();//根节点出栈  
	}
}
int main()
{
	ios::sync_with_stdio(false);
	memset(head,0,sizeof(head));
	memset(vis,false,sizeof(vis));
	memset(sta_num,0,sizeof(sta_num));
	memset(in,false,sizeof(in));
	cin>>n;
	for(signed i=1;i<=n;i++)
	{
		while(true)
		{
			int wills;
			cin>>wills;
			if(!wills)break;
			AddEdge(i,wills);
		}
	}
	for(signed i=1;i<=n;i++)
	if(!dfn[i])Tarjan(i);
	for(signed i=1;i<=n;i++)
	if(!dfn[i])Tarjan(i);
	for(signed i=1;i<=n;i++)sta_num[sta[i]]++;//统计同一栈内个数 
	for(signed k=1;k<=n;k++)
	{
		for(signed i=head[k];i;i=edge[i].next)
		{
			int to=edge[i].to;
			if(sta[to]!=sta[k])in[sta[to]]=true;
		}
	}
	for(signed i=1;i<=stan;i++)//枚举每一强连通分量 
	if(!in[i]) 
	ans+=sta_num[i];
	cout<<ans;
	return 0;
}

(QWQ

2020/7/21 12:01
加载中...