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