Codeforces Round #743 (Div. 2) C. Book (拓扑排序)
-
题意:一本书有\(n\)个chapters,想要读懂某个chapter需要先读懂其他chapters,你每次只能从第一章读到最后一章,问你最少读多少次可以将所有chapters都读懂。
-
题解:对某个chapter,我们从它所需要读懂的chapter连一条有向边到它,不难发现,某个chapter能读懂,当且仅当它的入度为\(0\),那这就是拓扑排序啊,只需在删边的过程中维护终点的最大值即可,对于终点在起点上面和下面分两种情况讨论,最后判断一下是不是所有边都能删完。
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int main() { int _; scanf("%d",&_); while(_--){ int n; scanf("%d",&n); vector<int> in(n+1),ans(n+1,0); vector<vector<int>> v(n+1); for(int i=1;i<=n;++i){ int k; scanf("%d",&k); in[i]=k; for(int j=1;j<=k;++j){ int x; scanf("%d",&x); v[x].pb(i); } } for(int i=1;i<=n;++i) sort(v[i].begin(),v[i].end()); queue<PII> q; for(int i=1;i<=n;++i){ if(in[i]==0){ q.push({i,1}); ans[i]=1; } } while(!q.empty()){ auto tmp=q.front(); q.pop(); for(auto id:v[tmp.fi]){ if(id<tmp.fi){ ans[id]=max(ans[id],tmp.se+1); } else ans[id]=max(ans[id],tmp.se); in[id]--; if(!in[id]) q.push({id,ans[id]}); } } int mx=0; bool flag=true; for(int i=1;i<=n;++i){ mx=max(mx,ans[i]); if(in[i]){ flag=false; break; } } if(!flag) puts("-1"); else printf("%d\n",mx); } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮