初学:
常用来表示事件之间的依赖关系,任务之间的调度
典型:依赖处理
在图论上,他是把DAG生成一个线性数列,表示这个图顶点之间的先后关系
过程
- 建立一个空队列,把所有入度为 0 的加入队列
- 然后从队列中取出一个节点,把该节点所有的出边删除,即入度 -1, 再判断该边通向的节点是否已经没有边连入(即入度是否为 0 ),若是,加入队列
- 重复,直到队列中不剩下任何节点
注:拓扑排序是对于DAG而言。如果需要判断图中是否存在环, 可以统计是否所有的节点都入过队。存在未入队的节点,代表存在环(无法拓扑排序) (因为入度不可能为0
1 #include <cstdio> 2 #include <algorithm> 3 4 #define MAXN 1111 5 #define MAXM 121111 6 7 int n, m, cnt; 8 int head[MAXN], q[MAXN], ru[MAXN]; 9 10 struct edge { 11 int y, next; 12 }e[MAXM]; 13 14 void add_edge(int x, int y) { 15 e[++cnt].y = y; 16 e[cnt].next = head[x]; 17 head[x] = cnt; 18 return ; 19 } 20 21 int main() { 22 scanf("%d%d", &n, &m); 23 for(int i = 1; i <= m; i++) { 24 int x, y; 25 scanf("%d%d", &x, &y); 26 ru[y]++; 27 add_edge(x, y); 28 } 29 int l = 1, r = 0; 30 for(int i = 1; i <= n; i++) {//入队 31 if(!ru[i]) { 32 r++; 33 q[r] = i; 34 } 35 } 36 while(l <= r) {//一直while到q里没元素 37 int now = q[l]; 38 l++;//首元素出队 39 for(int i = head[now]; i; i = e[i].next) { 40 int y = e[i].y; 41 ru[y]--;//终点为y的线段 入度—— 42 if(!ru[y]) {//如果入度减到了零 ,就让它进队(从后面入) 43 q[++r] = y; 44 } 45 } 46 } 47 for(int i = 1; i <= m; i++) printf("%d ", q[i]);//队列前m个是已经拓扑排序好了的元素 48 return 0; 49 }
另一种亲民的做法(STL大法好,真善...
int n,m; queue <int> q; for(int i = 1; i <= n; i++) if(ru[i] == 0) q.push(i); vector<int> ans; while(!q.empty()) { int u = q.front() ; q.pop() ; ans.push_back(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; ru[v]--; if(ru[v] == 0) { q.push(v); } } } if(ans.size()==n) { for(int i=0;i<ans.size();i++) printf( "%d ",ans[i] ); printf(" "); } else printf("No Answer! "); // ans 中的长度与n不相等,就说明无拓扑序列
相关题目
1. 要求字典序最小
解决方法: 改为优先队列即可
2153: D.ly的排队问题
Time Limit: 1 Sec Memory Limit: 128 MB
Description
马上要上体育课了,上体育课之前总归是要排个队的,ly作为班长,怎么排队的问题只能由她来解决,但是马上要上课了,ly又不清楚所有人的身高,她又不好意思问每个人的身高,因为这样会显的自己很不负责,于是她只能通过肉眼观察...那么问题来了,她只能观察出两个人A和B谁高谁矮,但是她没有办法排出一个序列。
ly都已经帮你出了两次主意赢过wjw,那么现在她需要你的帮助,你可以帮她吗?
(ly会告诉你A和B谁高,如果A比B高,会用A>B来表示)
Input
只有一组数据,每个比较结果占一行,读取到文件结束
Output
若输入数据无解,则输出"No Answer!",否则从高到低输出每个人的名字,中间没有分割符
若有多种情况,输出字典序最小的答案
Sample Input
E>A
A>S
S>Y
Sample Output
EASY
注: 这里的目的只是引入字典序最小该怎么做,具体的题解实际上是有点问题的
如: A>B B<C C<D 结果实际上是判断不出身高的(阔以自己试试
#include<cstdio> #include<queue> #include<set> #include<vector> #include<iostream> using namespace std; int main() { set <int> s; int ru[30] = {0}; vector <int> v[30]; char tmp[5]; // while(cin>>tmp) { while(~scanf("%s",tmp)) { s.insert(tmp[0]-'A'); s.insert(tmp[2]-'A'); if(tmp[1] == '>') { ru[tmp[2]-'A']++; v[tmp[0]-'A'].push_back(tmp[2]-'A'); } else { ru[tmp[0]-'A']++; v[tmp[2]-'A'].push_back(tmp[0]-'A'); } } priority_queue <int,vector<int>,greater<int> > q; for(int i = 0; i < 30; i++) if(ru[i]==0 && s.count(i) != 0) q.push(i); vector <int> ans; while(!q.empty()) { int now = q.top() ; q.pop() ; ans.push_back(now); for(int i = 0; i < v[now].size() ; i++) { int y = v[now][i]; ru[y]--; if(ru[y] == 0&&s.count(y)!=0) q.push(y); } } if(ans.size() != s.size() ) printf("No Answer!"); else for(int i = 0; i < ans.size() ; i++) printf("%c",ans[i]+'A'); printf(" "); return 0; } /* A>B B<C C<D */