1073: 选课
题目描述
计算机系有很多课程,比如数学分析、高等代数、计算机导论、C语言程序设计、面向对象程序设计、数据结构、算法设计与分析、数理逻辑、汇编程序设计、编译原理等等。其中有些课程是需要前面一些课程的基础,比如要修数据结构这么课必须先修C语言程序设计。
现在有一位外系学生想通过自学掌握计算机系所有的课程,他来找正在计算机系就读的您来给他自学课程的顺序提个建议。
输入
输入的第一行是一个正整数N(0 < N <= 500),表示计算机系总共需要修的课程的数目。课程从1-N编号。
输入的第二行包括N个课程的名字,每个课程名字由大写字母或小写字母或下划线组成,最长不超过40个字符,每两个相邻的名字用空格隔开。
输入的第三行到N+2行数据描述课程之间的依赖关系。第i+2行描述第i个课程的依赖关系,格式如下:
Mi m1 m2 m3 … mMi
其中Mi表示要修第i个课程共需要先修Mi个课程,后面跟随着Mi个课程编号,编号从小到大排列。
输出
输出N个课程的名字表示您建议的顺序,如果存在多个序列则您只需要输出其中任意一个。如果没有办法找到这样的序列则输出”Impossible!”(不需要输出引号,但是要输出感叹号,注意大小写)。
样例输入
9
Introduction_to_Computer_Science C_Programming_Language Data_Structure Design_and_Analysis_of_Algorithms Mathematical_Analysis Advanced_Algebra Probability_and_Statistics Numerical_Analysis Operating_System
0
1 1
2 1 2
3 1 2 3
0
0
1 5
2 5 6
2 1 2
样例输出
Introduction_to_Computer_Science Mathematical_Analysis Advanced_Algebra C_Programming_Language Probability_and_Statistics Data_Structure Design_and_Analysis_of_Algorithms Numerical_Analysis Operating_System
提示
来源
思路:完成一次简单的拓扑排序就可以。
代码:
#include<bits/stdc++.h>
#define maxn 510
using namespace std;
char name[maxn][50];
int Map[maxn][maxn],deg[maxn];
int N;
int vis[maxn];
void top_sort(){//普通的拓扑排序
queue<int> Q;
memset(vis,0,sizeof(vis));
for(int i=1;i<=N;i++)
if(!deg[i]) Q.push(i),vis[i]=1;
vector<int> ans;//先存储下来,因为有可能为impossible
while(!Q.empty()){
int tp=Q.front();Q.pop();
ans.push_back(tp);
for(int i=1;i<=N;i++) if(!vis[i] && Map[tp][i])
if(--deg[i]==0) Q.push(i),vis[i]=1;
}
if((int)ans.size()<N){printf("Impossible!\n");return;}
for(int i=0;i<ans.size();i++)
printf("%s%c",name[ans[i]],i+1==ans.size()? '\n':' ');
}
int main(){
//freopen("in.txt","r",stdin);
while(cin>>N){
for(int i=1;i<=N;i++)
scanf("%s",name[i]);
memset(Map,0,sizeof(Map));
memset(deg,0,sizeof(deg));
for(int i=1;i<=N;i++){
int t,a;
scanf("%d",&t);
deg[i]=t;
while(t--){
scanf("%d",&a);
Map[a][i]=1;
}
}
top_sort();
}
return 0;
}