11162 Acmer入门之道
时间限制:1000MS 内存限制:65535K
提交次数:29 通过次数:9
题型: 编程题 语言: 无限制
Description
方法向来是一个人取得成就的关键。于是每年都会有很多新生咨询老师,或者是师兄师姐学习方法,SCAU信软学院的莘莘学子们尤其踊跃。由于对专业缺乏了解, 很多新生都会为以下这些问题烦恼:比如是先学C++还是数据结构,又或者是先学Java还是Javascript。 对于软件专业技术人员,大致分两种,一类是做应用,一类是做研发。做应用就是写一些手机电脑软件、网页等,要求对C++、Jsp等比较熟悉;研发就是为一些 应用软件的功能实现提供算法或者研究更高效的算法,要求对数据结构和算法的研究比较深刻,这类人才在各大公司都很抢手。 ACM,毫无疑问,是培养研发人才的一个算法竞赛。作为通过了新生赛之初出茅庐的你,一定对如何搞好ACM很感兴趣吧O(∩_∩)O~…. ACM对知识面的要求很高,需要看各种各样的书籍,什么具体数学,黑书(《算法导论》),白书(《算法竞赛入门经典》),算法设计,数据结构,C++等等。 为了帮助新生迅速入门,SCAU ACM校队的队员们决定给大家一些建议。 Lrc:ACM的题目都是英文的,还是先学好英语再白书吧~ Lys:目测具体数学是全英的,你不学好英文怎么看,呵呵… Xdp:白书比黑书更基础,新生还是先学白书再学黑书咯… Hq:据说《计算思维方式》能修炼内功,算法设计能修炼外功,我认为应该先修炼内功吧。 Ly:算法设计作为大三的课本,比白书应该更适合入门吧(因为当年我只能看懂这本了~囧)。 Wyh:算法归根到底是数学思维的结晶,先大概学一下具体数学再学算法设计更容易学精。 Troy:算法里面很多是用到数据结构维护的,大家还是先学数据结构,打好基础再看算法设计呗。 Yys:Acmer最终还是要工作的,在弄懂黑书的各种算法后,应该要看一遍C++学习面向对象的思想。 Xym:C语言都学不好,怎么看数据结构呢? ……… 这些建议各种乱对不对?! Xym主席目测Ly的建议最没有建设性,于是命令Ly将这些科目按照建议排成一个特定的序列,好让师 弟师妹们参照这个顺序学习。对于某一条建议总会归纳出“要学B科目,应该先学A科目”,于是Xym主席 要求这个序列中B一定要排在A的后面。 经过各种尝试,Ly终于千辛万苦把序列弄出来了: C语言 英语 具体数学 计算思维方式 数据结构 算法设计 白书 黑书 C++ 可是第二天开会,各位队员又很积极地提出来了上万条建议,这次,Ly凌乱了。作为SCAU ACM 校队未来的希望,你能拯救下Ly吗?(⊙o⊙)… (出题人Ly)
输入格式
测试数据有多组。第一行输入一个整数T,表示测试数据的组数。 每组数据第一行两个整数n(n<=1000),m(m<=10000),分别代表建议涉及的科目数量和队员们提出的建议总数; 接下来n行,每行一个字符串Si,表示第i个科目的名称。所有字符串只有英文字母组成,长度均不超过15。 接下来m行,每行是一条建议,用两个字符串A,B表示,代表学科目B之前应该先学科目A。两个字符串之间用空格隔开。
输出格式
将所有科目按Xym主席的要求排成一个特定的序列,另外,如果A、B之间没有先后关系,科目名称字典序较小的将排在前面。然后按序列将科目名称逐一输出, 每个科目一行。 如果根据这些描述不能将所有科目排成所要求的序列,输出“No solution!”。
输入样例
2 9 9 English Whitebook Blackbook Datastructure Clanguage Cplusplus Modeofthinking Algorithm Math English Whitebook English Math Whitebook Blackbook Modeofthinking Algorithm Algorithm Whitebook Math Algorithm Datastructure Algorithm Blackbook Cplusplus Clanguage Datastructure 3 3 Whitebook Blackbook Algorithm Algorithm Whitebook Whitebook Blackbook Blackbook Algorithm
输出样例
Clanguage Datastructure English Math Modeofthinking Algorithm Whitebook Blackbook Cplusplus No solution!
典型的拓扑排序问题:每次选择入度为0且字典序最小的点(用优先队列维护),删去这个点和这个点的所有出边。
AC代码:
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <algorithm> #include <queue> #include <map> #include <cmath> #include <vector> #include <cstdlib> using namespace std; const int MAX=1005; vector<int>v[MAX]; //用邻接表存图 int n,m,in[MAX],ans[MAX]; char s1[20],s2[20]; char sub[MAX][20]; //保存科目 bool vis[MAX]; priority_queue<int,vector<int>,greater<int> > q; int cmp(const void*a,const void*b) { return strcmp((char*)a,(char*)b); } int get_num(char* a) //二分查找单词的序号 { int l=0,r=n; while(l<=r) { int mid=(l+r)/2; if(strcmp(sub[mid],a)==0) return mid; else if(strcmp(sub[mid],a)>0) r=mid-1; else l=mid+1; } return -1; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) v[i].clear(); for(int i=0; i<n; i++) { scanf("%s",sub[i]); } qsort(sub,n,20,cmp); memset(in,0,sizeof(in)); while(m--) { scanf("%s%s",s1,s2); int a=get_num(s1); int b=get_num(s2); v[a].push_back(b); in[b]++; } int cnt=0; memset(vis,false,sizeof(vis)); for(int i=0; i<n; i++) if(!vis[i]&&in[i]==0) q.push(i); while(!q.empty()) { int x=q.top(); //每次找字典序最小的 ans[cnt++]=x; vis[x]=true; q.pop(); for(int j=0; j<v[x].size(); j++) { in[v[x][j]]--; if(in[v[x][j]]==0&&!vis[v[x][j]]) q.push(v[x][j]); } } if(cnt<n) printf("No solution!\n"); else { for(int i=0; i<cnt; i++) printf("%s\n",sub[ans[i]]); } } return 0; }