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;
}