CF770C Online Courses In BSU 拓扑排序+dfs

CF770C Online Courses In BSU 拓扑排序+dfs

题目链接:https://codeforces.com/contest/770/problem/C

题目大意:一共有N个科目,其中有M个主要科目,只要M个主要科目都通过了,那么对应主人公就可以毕业了,也就是达成了目的。
现在有一个列表,表示要通过第i门课程需要先通过的科目列表。现在主人公希望得到一个通过科目的顺序,使得最终他通过最少的科目使得主人公毕业。
输出:至少修读课程数+任意一个修读课程的顺序即可,如果不行(有环)则输出-1

样例
输入:
6 2
5 3
0
0
0
2 2 1
1 4
1 5

输出:
5
1 2 3 4 5

思路:
先用一维vector–ma表示需要修读的主课,再用二维vector–v存图,具体做法为先dfs搜索主修课,即dfs(ma[i]),再从后向前搜索该主课的先修课,如果遇到已经存入结果数组的结点(vis[i]==2)则return,如果遇到重复且非结果的结点(vis[i]==1)则输出-1(存在环,无法成功),否则将该节点放入结果数组。

注:exit(0)------可以直接结束程序

#include<iostream>
#include<cstdio>
#include<set>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdlib>
#include<map>
using namespace std;
#define scan(n) scanf("%d",&n)
#define ll long long
const int maxn=1e5+5;
vector<int> ma,v[maxn],r;
int n,k,m,a;
int vis[maxn];
int cnt,ff;
void dfs(int x)
{
    
    
    if(vis[x]==2)
        return;
    vis[x]=1;
    for(int i=0;i<v[x].size();i++)
    {
    
    
        int to=v[x][i];
        if(vis[to]==1)
        {
    
    
            cout<<-1<<endl;
            exit(0);
        }
        dfs(to);
    }
    vis[x]=2;
    r.push_back(x);
}

int main()
{
    
    
    scanf("%d%d",&n,&k);
    memset(vis,0,sizeof(vis));
    for(int i=0;i<k;i++)
    {
    
    
        scanf("%d",&a);
        ma.push_back(a);
    }
    for(int i=1;i<=n;i++)
    {
    
    
        scanf("%d",&m);
        for(int j=0;j<m;j++)
        {
    
    
            scanf("%d",&a);
            v[i].push_back(a);
        }
    }
    for(int i=0;i<ma.size();i++)
    {
    
    
        dfs(ma[i]);
    }
    int l=r.size();
    cout<<l<<endl;
    for(int i=0;i<l-1;i++)
        cout<<r[i]<<' ';
    cout<<r[l-1]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40534166/article/details/98784054