linkkkk 题意:
每个书有页,每页都有前置页,学会这些前置页你才能够学会这页。每次阅读都是从
到
的顺序,问需要阅读几次才能够学完这本书。
思路:
对于每页和他的前置页,建图,表示学会
必须要学会
,如果说
的话,权值为
,表示两者在同一轮阅读里学会;否则,权值为
,表示下一轮才能够学会。
求最长路就是答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10,inf=0x3f3f3f3f;
int h[maxn],e[maxn],ne[maxn],w[maxn],idx;
int din[maxn],dp[maxn],n;
vector<int>top;
void add(int u,int v,int ww){
e[idx]=v,ne[idx]=h[u],w[idx]=ww,h[u]=idx++;
}
bool topsort(){
top.clear();
queue<int>q;
for(int i=1;i<=n;i++)
if(!din[i]) q.push(i);
while(!q.empty()){
int t=q.front();q.pop();
top.push_back(t);
for(int i=h[t];~i;i=ne[i]){
int j=e[i];
if(!--din[j]) q.push(j);
}
}
return top.size()==n;
}
int main(){
int _;cin>>_;
while(_--){
memset(h,-1,sizeof h);
idx=0;
memset(din,0,sizeof din);
cin>>n;
for(int i=1;i<=n;i++){
int m;cin>>m;
for(int j=1;j<=m;j++){
int x;cin>>x;
if(x>i) add(x,i,1);
else add(x,i,0);
din[i]++;
}
}
if(!topsort()) puts("-1");
else{
int ans=0;
memset(dp,0,sizeof dp);
for(int now:top){
for(int i=h[now];~i;i=ne[i]){
int j=e[i];
dp[j]=max(dp[j],dp[now]+w[i]);
}
}
for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
cout<<ans+1<<"\n";
}
}
return 0;
}
/*
5
4
1 2
0
2 1 4
1 2
5
1 5
1 1
1 2
1 3
1 4
5
0
0
2 1 2
1 2
2 2 1
4
2 2 3
0
0
2 3 2
5
1 2
1 3
1 4
1 5
0
*/