图论--拓扑排序模板

拓扑排序是图论中,按照有向边的进入顺序依次排序,在有环的图中不存在拓扑排序。

首先是小白书上的拓扑排序模板,用的是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 }

 

转载于:https://www.cnblogs.com/cenariusxz/p/4785058.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值