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;
}