zoukankan      html  css  js  c++  java
  • [CF770C] Online Courses In BSU

    一共有 (N) 个科目,其中有 (M) 个主要科目,只要 (M) 个主要科目都通过了,那么对应主人公就可以毕业了,也就是达成了目的。现在有一个列表,表示要通过第 (i) 门课程需要先通过的科目列表。现在主人公希望得到一个通过科目的顺序,使得最终他通过最少的科目使得主人公毕业。

    Solution

    如果有环,则无解

    对于每个主科目,从这个点开始,在反图上 DFS 即可,遇到已经标记的点就退出

    输出时按照拓扑序输出

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 100005;
    
    int n,m,t1,t2,t3,s[N],tim[N],fg[N],vis[N],ind;
    vector <int> g[N];
    
    namespace scc {
        vector <int> scc[N];
        int ind,f[N],siz[N],dfn[N],low[N],vis[N],s[N],bel[N],top,tot,m;
        void dfs(int p) {
            s[++top]=p;
            dfn[p]=low[p]=++ind;
            for(int i=0;i<g[p].size();i++) {
                int q=g[p][i];
                if(!dfn[q]) dfs(q), low[p]=min(low[p],low[q]);
                else if(!bel[q]) low[p]=min(low[p],dfn[q]);
            }
            if(dfn[p]==low[p]) {
                ++tot;
                for(int i=0;i!=p;) {
                    i=s[top--];
                    bel[i]=tot;
                    scc[tot].push_back(i);
                }
            }
        }
        void solve() {
            for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
        }
    }
    
    void dfs(int p) {
        vis[p]=1;
        for(int q:g[p]) if(vis[q]==0) dfs(q);
        tim[p]=++ind;
    }
    
    int cmp(int a,int b) {
        return tim[a]<tim[b];
    }
    
    void mark(int p) {
        fg[p]=1;
        for(int q:g[p]) if(fg[q]==0) mark(q);
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=m;i++) {
            cin>>s[i];
        }
        for(int i=1;i<=n;i++) {
            cin>>t1;
            while(t1--) {
                cin>>t2;
                g[i].push_back(t2);
            }
        }
        scc::solve();
        int flag=0;
        for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
        for(int i=1;i<=m;i++) mark(s[i]);
        for(int i=1;i<=n;i++) if(fg[i]&&scc::scc[scc::bel[i]].size()>1)
            flag=1;
        if(flag) {
            cout<<-1;
        }
        else {
    
            vector <int> ans;
            for(int i=1;i<=n;i++) if(fg[i]) ans.push_back(i);
            sort(ans.begin(),ans.end(),cmp);
            cout<<ans.size()<<endl;
            for(int i:ans) cout<<i<<" ";
        }
    }
    
    
  • 相关阅读:
    数据类型装换
    变量及数据类型
    27 网络通信协议 udp tcp
    26 socket简单操作
    26 socket简单操作
    14 内置函数 递归 二分法查找
    15 装饰器 开闭原则 代参装饰器 多个装饰器同一函数应用
    12 生成器和生成器函数以及各种推导式
    13 内置函数 匿名函数 eval,exec,compile
    10 函数进阶 动态传参 作用域和名称空间 函数的嵌套 全局变量
  • 原文地址:https://www.cnblogs.com/mollnn/p/12589097.html
Copyright © 2011-2022 走看看