linkkkk
题意:
每个书有n页,每页都有前置页,学会这些前置页你才能够学会这页。每次阅读都是从1到n的顺序,问需要阅读几次才能够学完这本书。
思路:
对于每页和他的前置页,建图,u − > v 表示学会v必须要学会u,如果说u < v u
求最长路+ 1就是答案。
代码:
#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 */