P2835 刻录光盘

强连通分量,缩点

求出每个强连通分量,缩点,统计入度为零的点。

好像能用并查集加floyd?

学不来

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;

int from[1000010],to[1000010],nex[1000010],head[10010],es;
int instack[10010],dfn[10010],low[10010],belong[10010],dfsnum,sccnum;
int sccenter[10010],sccout[10010];
stack<int> s;

void tarjan(int u)
{
	dfn[u]=low[u]=++dfsnum;
	instack[u]=true;
	s.push(u);
	for(int i=head[u];i;i=nex[i])
	{
		if(!dfn[to[i]])
		{
			tarjan(to[i]);
			low[u]=min(low[u],low[to[i]]);
		}
		else if(instack[to[i]])
			low[u]=min(low[u],dfn[to[i]]);
	}
	if(dfn[u]==low[u])
	{
		int v;
		++sccnum;
		do
		{
			v=s.top();
			s.pop();
			belong[v]=sccnum;
			instack[v]=false;
		}while(u!=v);
	}
	return ;
}

int main()
{
	ios::sync_with_stdio(false);
	int n,m;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>m;
		while(m!=0)
		{
			from[++es]=i;
			to[es]=m;
			nex[es]=head[i];
			head[i]=es;
			cin>>m;
		}
	}
	for(int i=1;i<=n;i++)	
		if(!dfn[i])
			tarjan(i);
	for(int i=1;i<=es;i++)
	{
		if(belong[from[i]]!=belong[to[i]])
		{
			++sccout[belong[from[i]]];
			++sccenter[belong[to[i]]];
		}
		else
			continue;
	}
	int out=0,enter=0;
	for(int i=1;i<=sccnum;i++)
	{
		if(sccout[i]==0)
			++out;
		if(sccenter[i]==0)
			++enter;
	}
	cout<<enter;
	return 0;
}
posted @ 2018-07-26 20:42  Coool  阅读(155)  评论(0编辑  收藏  举报