题目描述
一共有 NNN 个科目,其中有 MMM 个主要科目,只要 MMM 个主要科目都通过了,那么对应主人公就可以毕业了,也就是达成了目的。
现在有一个列表,表示要通过第 iii 门课程需要先通过的科目列表。现在主人公希望得到一个通过科目的顺序,使得最终他通过最少的科目使得主人公毕业。
思路
我们先想一下:怎样会无解?
即主修课程在环上面,相互嵌套,自然无解。
判断可以想到恶心的优秀的拓扑排序。
随后建反图跑 DFS 即可。
Code
#include<bits/stdc++.h>
using namespace std;
int n,k;
bool book[100010],schedule[100010];
int want[100010],t[100010],in[100010];
vector<int>G[100010],G2[100010],a;
bool TopoSort(void){
int arr[100010]={0};
queue<int>Q;
int tot=0,pot=0;
for(int i=1;i<=n;i++){
if(in[i]==0)Q.push(i);
}
while(!Q.empty()){
int F=Q.front();Q.pop();
arr[F]=++tot;
for(auto i:G[F]){
in[i]--;
if(in[i]==0)Q.push(i);
}
}
for(int i=1;i<=n;i++){
if(schedule[i]&&arr[i]==0)return false;
}
return true;
}
void DFS(int u){
if(book[u])return;
for(auto i:G2[u]){
DFS(i);
}
book[u]=true;
a.push_back(u);
}
int main(){
cin>>n>>k;
for(int i=1;i<=k;i++){
cin>>want[i];
schedule[want[i]]=true;
}
for(int i=1;i<=n;i++){
cin>>t[i];
for(int j=1;j<=t[i];j++){
int to;cin>>to;
G[to].push_back(i);
G2[i].push_back(to);
in[i]++;
}
}
if(!TopoSort()){
puts("-1");
}
else{
for(int i=1;i<=k;i++){
if(!book[want[i]])DFS(want[i]);
}
cout<<a.size()<<'\n';
for(int i=0;i<(int)a.size();i++){
cout<<a[i]<<' ';
}
}
return 0;
}