UVA 10305 Ordering Tasks(拓扑排序的队列解法)
题目链接:
https://vjudge.net/problem/UVA-10305#author=goodlife2017
题目描述
John有n个任务,但是有些任务需要在做完另外一些任务后才能做。
输入
输入有多组数据,每组数据第一行有两个整数1 <= n <= 100 和 m。n是任务个数(标记为1到n),m两个任务直接关系的数量。在此之后,有m行,每行有2个整数i和j,代表任务i必须在任务j之前完成。用n = m = 0结束整个输入。
输出
每一个数据对应一行n个整数,代表任务完成的顺序。
样例输入
5 4
1 2
2 3
1 3
1 5
0 0
样例输出
1 4 2 5 3
1 /* 2 问题 给出变量的个数n和m个二元组,输出任意一个从小到大的排序 3 解题思路 由题中所给的m个二元组可以得到每个点的入度,创建一个队列,先将入度为0的点加入队列, 4 然后依次出队,出队过程中将以该点为起点的那条边的终点的入度减去1,如果该点的入度变为0,就将该点也加入队列, 5 直到队列为空。 如果队列为空后,出队的点的个数等于总个数,则说明有拓扑序列,否则说明图内有环,够不成拓扑序列。 6 */ 7 #include<iostream> 8 #include<cstdio> 9 #include<cstring> 10 #include<vector> 11 #include<queue> 12 using namespace std; 13 14 const int maxn=110; 15 16 vector<int> g[maxn];//表示以g[i]为起点的边,比如表示1——2和1——3这两条边,g[1]中第一个元素为2,第二个元素为3 17 int rd[maxn]; 18 int topo[maxn]; 19 20 bool toposort(int n); 21 22 int main() 23 { 24 int m,n,i,u,v,j,flag; 25 while(scanf("%d%d",&n,&m), n + m != 0){ 26 for(i=1;i<=m;i++){ 27 scanf("%d%d",&u,&v); 28 flag=0; 29 for(j=0;j<g[u].size();j++) 30 if(g[u][j] == v) 31 { 32 flag=1; 33 break; 34 } 35 if(!flag) g[u].push_back(v); 36 } 37 38 if(toposort(n)){ 39 for(i=0;i<n-1;i++) 40 printf("%d ",topo[i]); 41 printf("%d\n",topo[n-1]); 42 } 43 44 for(i=0;i<=n;i++) 45 g[i].clear(); 46 } 47 return 0; 48 } 49 50 bool toposort(int n) 51 { 52 int i,j; 53 memset(rd,0,sizeof(rd)); 54 for(i=1;i<=n;i++){ 55 for(j=0;j<g[i].size();j++){ 56 rd[ g[i][j] ]++; 57 } 58 } 59 60 int t=0; 61 queue<int> q; 62 for(i=1;i<=n;i++) 63 if(rd[i]==0){ 64 q.push(i); 65 } 66 67 int x; 68 while(!q.empty()){ 69 x=q.front(); 70 q.pop(); 71 topo[t++]=x; 72 for(i=0;i<g[x].size();i++){ 73 j=g[x][i]; 74 rd[ j ]--; 75 76 if(rd[j]==0) 77 q.push(j); 78 } 79 } 80 81 if(t==n) return 1; 82 return 0; 83 }
欢迎交流,共同进步——