先建图,根据边计算所有顶点的入度,然后扫一遍将入度为0的顶点入队,
同时,该顶点指向的顶点入度减一,在队列中重复此操作,
直到所有点都被分离,如果顶点没有全部分离出来,
那么说明有环,不存在拓扑序,无解,详情见代码。
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #include<map>
7 #include<set>
8 #include<vector>
9 #include<queue>
10 #include<list>
11 #include<stack>
12 //#include<unordered_map>
13 using namespace std;
14 #define ll long long
15 const int mod=1e9+7;
16 const long long int inf=1e18+7;
17
18 const int maxn=1e5+10;
19 vector<int>edge[maxn];
20 int in[maxn];
21 int n,m;
22 void toupu()
23 {
24 queue<int>q;
25 for(int i=1;i<=n;i++)
26 {
27 if(in[i]==0)//找到入度为0顶点入队
28 {
29 q.push(i);
30 }
31 }
32 vector<int>ans;//存拓扑序
33 while(!q.empty())
34 {
35 int now=q.front();//取出队首
36 q.pop();
37 ans.push_back(now);
38 for(int i=0;i<edge[now].size();i++)
39 { //去掉这个点涉及的边
40 in[edge[now][i]]--;//相连边的另一个顶点入度减一
41 if(in[edge[now][i]]==0)//该点入度减为0
42 {
43 q.push(edge[now][i]);//入队
44 }
45 }
46 }
47 if(ans.size()!=n)//无n个顶点
48 {
49 cout<<-1<<endl;//无解
50 return ;
51 }
52 cout<<ans[0];
53 for(int i=1;i<ans.size();i++)//输出拓扑序
54 cout<<" "<<ans[i];
55 cout<<endl;
56 }
57
58 int main()
59 {
60 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
61 cin>>n>>m;//n个点,m条有向边
62 for(int i=0;i<=n;i++)//初始化图
63 edge[i].clear();
64 memset(in,0,sizeof(in));//初始化入度
65 int x,y;
66 for(int i=0;i<m;i++)
67 {
68 cin>>x>>y;
69 edge[x].push_back(y);//建图
70 in[y]++;//入度加一
71 }
72 toupu();//求拓扑序
73 return 0;
74 }
75 /* 例
76 6 8
77 1 2
78 1 3
79 1 4
80 3 2
81 3 5
82 4 5
83 6 4
84 6 5
85
86 1 6 3 4 2 5
87 */