其实就是手打了个Tarjan的模板
输出的时候注意是入度为0的点的个数和max(入度0的个数,出度0的个数),在n=1时特判为0即可
——以后图论要渐渐模板化,方便使用
#include <cstdio>
#include <iostream>
using namespace std;
struct E
{
int from,to,next;
} e[];
int Enum=,sttop=;
int first[];
int dfn[],low[];
bool que[];
int tar[];
int sum,n,_ans,ans;
int df;
int num[];
int st[];
void add(int from,int to)
{
E New;
New.from=from;
New.to=to;
New.next=first[from];
e[++Enum]=New;
first[from]=Enum;
}
void tarjan_dfs(int u)
{
st[++sttop]=u;
int v;
que[u]=;
dfn[u]=low[u]=++df;
for(int i=first[u];i;i=e[i].next)
{
v=e[i].to;
if(dfn[v]==)
{
tarjan_dfs(v);
low[u]=min(low[u],low[v]);
}
else
if(que[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
sum++;
do
{
v=st[sttop--];
que[v]=;
tar[v]=sum;
}while(u!=v);
}
}
int tarjan()
{
sum=;df=;sttop=;
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan_dfs(i);
for(int i=;i<=n;i++)
first[i]=;//清空原有边
for(int i=;i<=Enum;i++)
if(tar[e[i].from]!=tar[e[i].to])
{
e[i].from=tar[e[i].from];
e[i].to=tar[e[i].to];
e[i].next=first[e[i].from];
first[e[i].from]=i;
num[e[i].to]++;
}
return sum;
}
void dfs(int k)
{
if(first[k])
for(int i=first[k];i;i=e[i].next)
dfs(e[i].to);
else
if(!que[k])
{
_ans++;
que[k]=;
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int k;
scanf("%d",&k);
while(k>)
{
add(i,k);
scanf("%d",&k);
}
}
n=tarjan();
for(int i=;i<=n;i++)
que[i]=;
for(int i=;i<=n;i++)
if(!num[i])
{
ans++;
dfs(i);
}
printf("%d\n%d\n",ans,n==?:max(ans,_ans));
return ;
}