题目链接:C.Book
思路:基本上就是拓扑排序模板题,一些细节会给在代码当中给与一定注释
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int h[N],e[N],ne[N],idx,n,en[N],day[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int top()
{
int sum=0,maxs=1;
queue<int> q;
for(int i=1;i<=n;i++)
{
if(!en[i])q.push(i),sum++,day[i]=1;//先找出入度为0的结点
//即第一天可以阅读完成的章节
}
if(!sum)return -1;//如果没有入度为0的结点那么说明不能形成拓扑序列
while(q.size())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(t>=j)day[j]=max(day[t]+1,day[j]),maxs=max(day[j],maxs);//这里踩大坑
//写成了day[j]=day[t]+1,这样做的话可能会导致所需阅读的天数可能越来越少!!!
else day[j]=max(day[t],day[j]);//这里一样
en[j]--;
if(!en[j])q.push(j),sum++;
}
}
if(sum!=n)return -1;
return maxs;
}
int main()
{
int t,m,x;
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
idx=0;
for(int i=1;i<=n;i++)//之前用了memset超时了..
{
e[i]=0;h[i]=-1;ne[i]=0;en[i]=0;day[i]=0;
}
for(int i=1;i<=n;i++)
{
cin>>m;en[i]=m;//en[i]为i结点的入度
for(int j=1;j<=m;j++)
{
cin>>x;
add(x,i);
}
}
cout<<top()<<endl;
}
}