返回顶部

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;
    }
    
    
posted @ 2021-09-22 17:11  Rayotaku  阅读(52)  评论(0编辑  收藏  举报