文章目录
C. Book
题意:
有一本书有
n
n
n个章节,读懂一个章节,需要读懂它所有的前置章节,看一便书只能从顺序从第一章看到最后一章,问能否读懂所有章节,如果能,输出最少需要几遍书,否则输出
−
1
-1
−1
思路:拓扑排序+dp
状态表示:
d
p
[
i
]
dp[i]
dp[i]表示读懂这个章节所需要的最小遍数
边界条件:如果 i i i没有前置章节(入度为0), d p [ i ] = 1 dp[i]=1 dp[i]=1
状态转移:
将一个章节的所有前置章节与这个章节连一条有向边,做拓扑排序,如果没有拓扑排序,直接输出
−
1
-1
−1,在拓扑排序中考虑转移方程,如果
a
→
b
a \to b
a→b,如果
a
<
b
a<b
a<b,
a
,
b
a,b
a,b可以在一遍读完,
d
p
[
b
]
=
m
a
x
(
d
p
[
b
]
,
d
p
[
a
]
)
dp[b] =max(dp[b],dp[a])
dp[b]=max(dp[b],dp[a]) ,如果
a
>
b
a > b
a>b,那么
b
b
b只能在下一遍读,
d
p
[
b
]
=
m
a
x
(
d
p
[
b
]
,
d
p
[
a
]
+
1
)
dp[b]=max(dp[b],dp[a]+1)
dp[b]=max(dp[b],dp[a]+1),
这里要取
m
a
x
max
max因为
d
p
[
i
]
dp[i]
dp[i]是一个下界,需要读懂所有章节,就必须满足前置章节所有下界,相当于满足下界的最大值,最后
a
n
s
=
m
a
x
(
a
n
s
,
d
p
[
1
∼
n
]
)
ans=max(ans,dp[1\sim n])
ans=max(ans,dp[1∼n]),即为读懂所有章节的最小遍数
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define int ll
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define endl '\n'
#define SZ(x) (int)(x.size())
#define ALL(x) (x).begin(),(x).end()
#define mst(a,x) memset(a,x,sizeof(a))
#define ls u<<1
#define rs u<<1|1
mt19937 rnd(time(0));
typedef vector<int> VI;
typedef pair<int,int> PII;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
int n;
int h[N],ne[N],e[N],idx;
int in[N];
int dp[N];
int q[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool topsort(){
int hh=0,tt=-1;
rep(i,1,n)
if(!in[i]){
q[++tt]=i;
dp[i]=1;
}
while(hh<=tt){
int t=q[hh++];
for(int i=h[t];~i;i=ne[i]){
int j=e[i];
if(j<t) dp[j]=max(dp[j],dp[t]+1);
else dp[j]=max(dp[j],dp[t]);
if(--in[j]==0) q[++tt]=j;
}
}
return tt==n-1;
}
void solve(){
cin>>n;
rep(i,1,n) dp[i]=in[i]=0,h[i]=-1;
rep(i,1,n){
int t;cin>>t;
rep(j,1,t){
int x;cin>>x;
add(x,i);
in[i]++;
}
}
if(topsort()){
int ans=0;
rep(i,1,n) ans=max(ans,dp[i]);
cout<<ans<<endl;
}else cout<<"-1\n";
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int _;cin>>_;while(_--)
solve();
return 0;
}