拓扑排序

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,该排序满足这样的条件——对于图中的任意两个结点uv,若存在一条有向边从u指向v,则在拓扑排序中u一定出现在v前面。
当且仅当一个有向图为有向无环图(DAG)时才存在对应于该图的拓扑排序。每一个有向无环图都至少存在一种拓扑排序。
拓扑排序的实现:
①Kahn算法【常可用来判断该图是否是DAG(有向无环图)】
算法复杂度为O(v+e)。
算法实现:循环执行以下两步直到不存在入度为0的顶点为止。
(1)选择一个入度为0的顶点并输出之;(2)从网中删除此顶点及其所有出边。
循环结束后,若输出的顶点数小于网中的顶点数,则该图存在回路,否则输出的顶点序列就是拓扑序列,该图也即为DAG图。
该算法可借助队列实现。类似于bfs:首先将入度为0的顶点入队,取出队头元素进行拓展,找其邻接点,每个邻接点的入度-1,当入度变为0时则入队。循环此操作直到队列为空。出队顶点序列即为拓扑序列。
int k=0;
void toposort()
{queue<int>q;for(int i=1;i<=n;i++)if(!indegree[i])q.push(i);while(!q.empty()){int u=q.front();q.pop();cout<<u<<' ';k++;//输出拓扑序列,计数+1for (u的每个邻接点v){ //vector或链式前向星建图,遍历方式不一样indegree[v]--;//删除边(u, v),即让v的入度-1;if (!indegree(v) )q.push(v);}}
}
if (k!=n)存在环;
else不存在环,为DAG图;   

②基于DFS的拓扑排序算法( 复杂度O(V+E) )

1)DFS求给定DAG图的拓扑序列【前提:已知图是DAG】

topo数组存求得的拓扑序列
int k=0;
void DFS(int x)
{vis[x]=1;for(遍历x的邻接点j){if(!vis[j])DFS(j);}topo[k++]=x;//用栈存
}
void toposort()
{for(int i=1;i<=n;i++){ //遍历每个顶点if(!vis[i])DFS(i);}for(int j=k-1;j>=0;j--)cout<<topo[i]<<' ';//逆序输出数组,所得序列即为拓扑序列
}

2)DFS判断有向图是否有环(是否存在合法的拓扑序列):

对一个节点x进行dfs,判断是否能从x回到自己这个节点,即是否存在x到x的回路。

这里需用一个color数组标记节点的状态:-1代表未访问,0代表正在被访问,1代表已被访问过

#include<bits/stdc++.h>
using namespace std;
int n,e;//n个顶点(1<=n<=100),e条边
int color[105];//color数组表示每个结点的状态
vector<int>G[105];//vector邻接表建图
bool flag;//为真则存在环
void DFS(int x)
{if(flag)//如果有环就返回,否者继续搜索return;color[x]=0;//x正在被访问,状态为0for(int i=0;i<G[x].size();i++){if(color[G[x][i]]==-1)//与x相连的结点状态为-1,则该节点未被访问,继续搜索dfs(G[x][i]);else if(color[G[x][i]]==0){//与x相连的结点状态也为0,代表有环,返回flag=true;return;}}color[x]=1;//标记x状态为已被访问过了
}
int main()
{int u,v;while(~scanf("%d%d",&n,&e)){flag=false;for(int i=1;i<=n;i++)//二维vector初始化for(int j=0;j<G[i].size();j++)G[i].pop_back();memset(color,-1,sizeof(color));//初始化为未访问for(int i=1;i<=e;i++){scanf("%d%d",&u,&v);G[u].push_back(v);}DFS(1);if(!flag)printf("有向图无环,存在合法的拓扑序列\n");else printf("有向图有环,不存在合法的拓扑序列\n");}return 0;
}

UVA10305 给任务排序 Ordering Tasks

题意:

John有n个任务要做,每个任务在做之前要先做特定的一些任务。

输入第一行包含两个整数n和m,其中1<=n<=100。 n表示任务数,而m表示有m条任务之间的关系。 接下来有m行,每行包含两个整数i和j,表示任务i要在j之前做。

当读入两个0(i=0,j=0)时,输入结束。

输出包含q行,每行输出一条可行的安排方案。

输入:
5 4
1 2
2 3
1 3
1 5
0 0
输出:
1 4 2 5 3

题解:

裸拓扑排序

Code:

Kahn算法+vector邻接表

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int n,m,indegree[105];
void toposort(vector<vector<int> >G)
{int space=0;queue<int>q;for(int i=1;i<=n;i++)if(!indegree[i])q.push(i);while(!q.empty()){int x=q.front();q.pop();space?printf(" "):printf(""),space=1;printf("%d",x);for(int j=0;j<G[x].size();j++){indegree[G[x][j]]--;if(!indegree[G[x][j]])q.push(G[x][j]);}}
}
int main()
{int u,v;while(~scanf("%d%d",&n,&m)&&n){vector<vector<int> >G(n+5);//开n+5行的vector二维数组indegree[105]={};while(m--){scanf("%d%d",&u,&v);G[u].push_back(v);indegree[v]++;}toposort(G);puts("");}return 0;
}

基于DFS的拓扑排序+链式前向星建图

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
struct node{int to,next;
}G[105];
int head[105],cnt;
void add(int u,int v)
{G[cnt].to=v;G[cnt].next=head[u];head[u]=cnt++;
}
int n,e,indegree[105],ans[105],k,vis[105];
void DFS(int rec)
{vis[rec]=1;for(int j=head[rec];~j;j=G[j].next){if(!vis[G[j].to])DFS(G[j].to);}ans[k++]=rec;
}
void toposort()
{for(int i=1;i<=n;i++){if(!vis[i])DFS(i);}int q=1;for(;k>0;){q?cout<<"":cout<<" ";q=0;cout<<ans[--k];}
}
int main()
{int u,v;while(~scanf("%d%d",&n,&e)&&n){cnt=0;memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));for(int i=1;i<=e;i++){scanf("%d%d",&u,&v);add(u,v);}toposort();puts("");}return 0;
}

拓扑排序【Kahn算法(bfs)和dfs求拓扑序列及判环】相关推荐

  1. 拓扑排序(Kahn算法和基于DFS求解法)

    拓扑排序是对有向无环图(DAG)进行排序,从而找到一个序列.该序列满足对于任意一对不同的顶点u,v∈V,若G中存在一条从u->v的边,则在此序列中u在v前面. 拓扑排序也可以用来判断一个有向图是 ...

  2. 拓扑排序----Kahn算法和字典序最小的拓扑排序

    一.拓扑排序定义: 二.卡恩算法(Kahn): 1.Kahn算法介绍: 有向无环图DAG至少具有一个度数为0的顶点和一个度数为0的顶点. 证明:上述事实有一个简单的证明,即DAG不包含循环,这意味着所 ...

  3. (数据结构)有向图的拓扑排序 Kahn算法

    拓扑排序是对有向无圈图的顶点的一种排序,使得如果存在一条从vi到vj的路径,那么在排序中,vi必须出现在vj的前面. 首先,我们需要准备一个vector<int> link[maxn],l ...

  4. DAG拓扑排序-Kahn算法

    拓扑排序就是对一个有向无环图进行排序,使其变成一个线性关系,并且保证其前后的位置关系不改,简言之,就是把一个偏序变成一个全序(线性序). 拓扑排序有两种算法,一种是借助DFS排序,另一种是卡恩算法,这 ...

  5. 拓扑排序-Kahn算法

    题目描述 众所周知, TT 是一位重度爱猫人士,他有一只神奇的魔法猫. 有一天,TT 在 B 站上观看猫猫的比赛.一共有 N 只猫猫,编号依次为1,2,3,-,N进行比赛.比赛结束后,Up 主会为所有 ...

  6. 拓扑排序——Kahn算法

    Kahn算法 #include <iostream> #include<vector> #include<list> using namespace std;// ...

  7. 拓扑排序Kahn算法

    拓扑排序 介绍 思路 操作过程 完美图解 代码模板 介绍 拓扑排序,整体是给出n个事件先后关系,来确定n个事件最终的先后关系 思路 很好理解 操作过程 我们可以理解成一个有向图如果x事件在y事件的前面 ...

  8. Poj 1094 拓扑排序Kahn

    Poj 1094 拓扑排序Kahn Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4133 ...

  9. 记录两种搜索遍历算法——BFS和DFS

    " 你所有流过的泪,是一条渡你的河, 你所有受过的苦,将照亮你前方的路:岁月从没有放过我们,我们也不能辜负岁月." 最近过的不好~ 被虐 自信全无 各种害怕.自卑~ 唯有努力前行, ...

最新文章

  1. MathWorks的AI之路:面向工业场景,打通开发到部署的全链路
  2. Node.js-sublime text3 配置node.js(ERROR: The process node.exe not found.)
  3. Intellij IDEA(Android Studio)好用的插件和软件
  4. 裘宗燕-数据结构与算法python描述-ppt及源代码
  5. Android搜索框效果
  6. Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)(转)
  7. 论文浅尝 | BoxE:一种基于Box的知识图谱表示学习模型
  8. switch matlab c语言,matlab switch语句使用
  9. ES6-异步编程-Promise对象
  10. SharePoint 2013 中自定义WCF服务
  11. boost operator 实例代码
  12. 关于服务器发生w32tm的ID:29,ID:47等错误
  13. idea的html表单老提交后显示404,IDEA项目部署顺利后访问一直404
  14. php开发实例大全pdf百度云盘_互联网大厂 主要使用哪些开发语言
  15. 卖白菜|贱卖白菜|卖大白菜|贱卖大白菜|买白菜
  16. 2015 2020 r4烧录卡 区别_每分时长来看2010年与2015年与2020年澳网男单决赛的区别...
  17. java 12306验证码识别_12306验证码图片库大全
  18. SecureCRT键盘无法输入
  19. 手机usb计算机无法连接,手机usb连不上电脑怎么办实际解决
  20. Irvue for Mac(苹果壁纸软件)

热门文章

  1. codeforces - 1315C - 思维题
  2. cesium clock时间轴速度自定义
  3. android手机如何拥有苹果表情包,安卓手机emoji表情怎么改成苹果的
  4. nanomsg----pair1 的介绍
  5. word 章节、图片(带章节)、公式自动编号
  6. linux 导出数据库数据或者表结构
  7. SAP ABAP基础
  8. [19考研]政治英语数学专业课 复习书籍推荐!
  9. Oracle SQL 性能优化规范
  10. 码云图床php,PHP 脚本实现 Markdown 文章上传到七牛图床