拓扑排序是图论中,按照有向边的进入顺序依次排序,在有环的图中不存在拓扑排序。
首先是小白书上的拓扑排序模板,用的是DFS建立拓扑排序,但是似乎除了一般的拓扑排序以外什么都做不了……求字典序最小或者输出全部答案都不适用……
1 #include<stdio.h>
2 #include<string.h>
3
4 const int maxn=1e5+5;
5 const int maxm=1e5+5;
6
7 int head[maxn],point[maxm],nxt[maxm],size;
8 int vis[maxm],topo[maxm],t;
9
10 void init(){
11 memset(head,-1,sizeof(head));
12 size=0;
13 }
14
15 void add(int a,int b){
16 point[size]=b;
17 nxt[size]=head[a];
18 head[a]=size++;
19 }
20
21 bool dfs(int s){
22 vis[s]=-1;
23 for(int i=head[s];~i;i=nxt[i]){
24 int j=point[i];
25 if(vis[j]==-1)return 0;
26 if(!vis[j]&&!dfs(j))return 0;
27 }
28 vis[s]=1;
29 topo[t--]=s;
30 return 1;
31 }
32
33 bool toposort(int n){
34 t=n;
35 memset(vis,0,sizeof(vis));
36 for(int i=1;i<=n;++i){
37 if(!vis[i]){
38 if(!dfs(i))return 0;
39 }
40 }
41 return 1;
42 }
接下来是BFS实现的,一般用队列就可以满足需要了,如果要求字典序最小,可以改成优先队列实现,但是只能输出一个排序。在过程中可以加入判断,每次从队列中取出元素删除后,判断队列是否为空,若任意一次不为空则可以说明拓扑序不唯一。
1 #include<stdio.h>
2 #include<string.h>
3 #include<queue>
4 using namespace std;
5
6 const int maxn=1e5+5;
7 const int maxm=1e5+5;
8
9 int ans,n;
10 int head[maxn],point[maxm],nxt[maxm],size;
11 int id[maxn],num[maxn];
12
13 void init(){
14 memset(head,-1,sizeof(head));
15 size=0;
16 }
17
18 void add(int a,int b){
19 point[size]=b;
20 nxt[size]=head[a];
21 head[a]=size++;
22 id[b]++;
23 }
24
25 bool topo(){
26 // priority_queue<int,vector<int>,greater<int> >q;
27 queue<int>q;
28 for(int i=1;i<=n;++i)if(!id[i])q.push(i);
29 int cnt=0;
30 while(!q.empty()){
31 int u=q.front();q.pop();
32 cnt++;
33 for(int i=head[u];~i;i=nxt[i]){
34 int j=point[i];
35 id[j]--;
36 if(!id[j])q.push(j);
37 }
38 }
39 if(cnt==n)return 1;
40 return 0;
41 }
然后是DFS版,可以实现输出所有拓扑序的输出,并且通过进入DFS的顺序的控制也基本能实现字典序输出。
1 #include<stdio.h>
2 #include<string.h>
3
4 const int maxn=1e5+5;
5 const int maxm=1e5+5;
6
7 int head[maxn],point[maxm],nxt[maxm],size;
8 int ma[maxm][maxm],id[maxm],n,vis[maxm],v[maxm];
9 int ans[maxm];
10
11 void init(){
12 memset(head,-1,sizeof(head));
13 size=0;
14 }
15
16 void add(int a,int b){
17 point[size]=b;
18 nxt[size]=head[a];
19 head[a]=size++;
20 id[b]++;
21 }
22
23 void dfs(int s,int t){
24 ans[t]=s;
25 v[s]=1;
26 if(t==n){
27 for(int i=1;i<=n;++i){
28 printf("%d",ans[i]);
29 if(i==n)printf("\n");
30 else printf(" ");
31 }
32 v[s]=0;
33 return;
34 }
35 int que[maxn],cnt=0;
36 for(int i=1;i<=n;++i){
37 if(ma[s][i])id[i]--;
38 if(vis[i]&&!id[i]&&!v[i])que[++cnt]=i;
39 }
40 for(int i=1;i<=cnt;++i)dfs(que[i],t+1);
41 for(int i=1;i<=n;++i)if(ma[s][i])id[i]++;
42 v[s]=0;
43 }
44
45 for(int i=1;i<=n;++i){
46 if(vis[i]&&!id[i])dfs(i,1);
47 }