//https://pintia.cn/problem-sets/15/problems/861
//任务调度的合理性
//思路:与其从下往上搜索母节点,不如使用母节点主动去消灭子节点中牵扯到的子节点
//征北军的铁蹄踏上了远东的领土……
//为了清除敌方残余力量,他们挑选出自己信任的当地百姓
//给予他们以下一项决定生死的权利:担保——信任的力量
//这些百姓在使用这项权利之前,他们的怀疑值f[x][0]已经变成了0.
//行使这项权利(或者说完成这项任务)之后,他们被征北军视作死忠
//他们的怀疑值f[x][0]将会变成-1——以后你就不用再来做这种容易引发选择困难症的苦差事了^-^
//回归正题:
//在每一轮过程中,这些拥有权利的百姓会依次上场
//此时,在场其他的被怀疑百姓如果正好拥有当前担保百姓的信物,那么他们的怀疑值就会减1
//每轮结束后:那些新成为怀疑值为0的百姓就会在下一轮履行担保任务的职责
//如果一轮中没有新的良善人士——
//要么已经排除异己结束,要么就是敌对分子的怀疑值没有被完全消除
//看看是否全部变成死忠(只要上过场就可以),若是,输出1;若否,输出0.
#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
#define MAX 105
int f[MAX][MAX];
//f[x][0]用来记录动态的剩余未被确认可行元素个数
//f[x][y>0]用来记录先行任务编号
int n;
int num[MAX];
//num[x]用来记录静态的一开始每个任务的先行任务个数
int main()
{
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>f[i][0];
num[i]=f[i][0];
for(j=1;j<=f[i][0];j++) cin>>f[i][j];
}
int cnt;
//cnt用来记录每次原非母节点被改变为母节点的个数,如果没有,说明存在环或者已经全部确认是可以完成的任务
//存在环==f[x][0]!=-1;(已经用于确认过其他节点的母节点的f[x][0]会被打上-1的标记,
//被打上f[x][0]=0的标记意味着还没有被用于确认过其他节点)
do
{
cnt=0;
for(j=1;j<=n;j++)
{
if(f[j][0]==0)
{
for(k=1;k<=n;k++)
{
if(f[k][0]>0)
{
for(int l=1;l<=num[k];l++)
{
if(f[k][l]==j)
{
f[k][0]--;
break;
}
}
}
}
f[j][0]=-1;
}
}
for(i=1;i<=n;i++)
{
if(f[i][0]==0) cnt++;
}
}while(cnt>0);
for(i=1;i<=n;i++)
{
if(f[i][0]!=-1) break;
}
if(i==(n+1)) cout<<1;
else cout<<0;
return 0;
}
//任务调度的合理性
//思路:与其从下往上搜索母节点,不如使用母节点主动去消灭子节点中牵扯到的子节点
//征北军的铁蹄踏上了远东的领土……
//为了清除敌方残余力量,他们挑选出自己信任的当地百姓
//给予他们以下一项决定生死的权利:担保——信任的力量
//这些百姓在使用这项权利之前,他们的怀疑值f[x][0]已经变成了0.
//行使这项权利(或者说完成这项任务)之后,他们被征北军视作死忠
//他们的怀疑值f[x][0]将会变成-1——以后你就不用再来做这种容易引发选择困难症的苦差事了^-^
//回归正题:
//在每一轮过程中,这些拥有权利的百姓会依次上场
//此时,在场其他的被怀疑百姓如果正好拥有当前担保百姓的信物,那么他们的怀疑值就会减1
//每轮结束后:那些新成为怀疑值为0的百姓就会在下一轮履行担保任务的职责
//如果一轮中没有新的良善人士——
//要么已经排除异己结束,要么就是敌对分子的怀疑值没有被完全消除
//看看是否全部变成死忠(只要上过场就可以),若是,输出1;若否,输出0.
#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
#define MAX 105
int f[MAX][MAX];
//f[x][0]用来记录动态的剩余未被确认可行元素个数
//f[x][y>0]用来记录先行任务编号
int n;
int num[MAX];
//num[x]用来记录静态的一开始每个任务的先行任务个数
int main()
{
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>f[i][0];
num[i]=f[i][0];
for(j=1;j<=f[i][0];j++) cin>>f[i][j];
}
int cnt;
//cnt用来记录每次原非母节点被改变为母节点的个数,如果没有,说明存在环或者已经全部确认是可以完成的任务
//存在环==f[x][0]!=-1;(已经用于确认过其他节点的母节点的f[x][0]会被打上-1的标记,
//被打上f[x][0]=0的标记意味着还没有被用于确认过其他节点)
do
{
cnt=0;
for(j=1;j<=n;j++)
{
if(f[j][0]==0)
{
for(k=1;k<=n;k++)
{
if(f[k][0]>0)
{
for(int l=1;l<=num[k];l++)
{
if(f[k][l]==j)
{
f[k][0]--;
break;
}
}
}
}
f[j][0]=-1;
}
}
for(i=1;i<=n;i++)
{
if(f[i][0]==0) cnt++;
}
}while(cnt>0);
for(i=1;i<=n;i++)
{
if(f[i][0]!=-1) break;
}
if(i==(n+1)) cout<<1;
else cout<<0;
return 0;
}