zoukankan      html  css  js  c++  java
  • 图论--拓扑排序模板

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

    首先是小白书上的拓扑排序模板,用的是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("
    ");
    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 }
  • 相关阅读:
    Linux环境进程间通信
    monitor
    用prctl给线程命名
    openfire本地环境搭建和openfire插件开发实例
    ubuntu12.04的vim配置
    SensorThread线程
    AndroidPN中的心跳检测
    openfire插件开发之完美开发
    poj3322 Bloxorz I
    设计模式总结
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4785058.html
Copyright © 2011-2022 走看看