拓扑排序

图的拓扑排序——卡恩算法

我的梦境 提交于 2020-02-25 10:25:54
拓扑排序 有向图的拓扑排序是其顶点的线性排序,使得对于从顶点u 到顶点v 的每个有向边uv ,u 在排序中都在v 之前。 在图论中,由一个 有向无环图 的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个 拓扑排序 ( Topological sorting)。 每个顶点出现且只出现一次; 若A在序列中排在B的前面,则在图中不存在从B到A的路径 。 //#include<Windows.h> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int maxn = 105; const int MAX_E = 10005; const int MAX_V = 105; struct ENode { int to; int Next; }; ENode Edegs[MAX_E]; int Head[MAX_V]; int tnt; void Add_ENode(int w, int v) { ++tnt; Edegs[tnt].to = v; Edegs[tnt].Next = Head[w]; Head[w] = tnt; /*可以拓扑排序则保证这是一个有向图*/ } int IN_degree[maxn];//记录每个点的入度; int Queue[maxn];

[HIHO1174]拓扑排序·一(拓扑排序)

拟墨画扇 提交于 2020-02-25 08:58:21
题目链接:http://hihocoder.com/problemset/problem/1174 题意:判断一个有向图是否有环,用拓扑排序,结论就是每次取出点的时候统计一下现在剩下几个点,最后没有剩下点就是无环的。 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime

【图论】拓扑排序

帅比萌擦擦* 提交于 2020-02-22 17:41:56
板子题:hihocoder-1174 # include <bits/stdc++.h> # define ll long long # define endl '\n' using namespace std ; const int INF = 0x3f3f3f3f ; const int mod = 1e9 + 7 ; const int maxn = 1e5 + 10 ; ll n , m , num ; ll InDeg [ maxn ] ; vector < ll > vec [ maxn ] ; queue < ll > q ; bool topsort ( ) { while ( ! q . empty ( ) ) q . pop ( ) ; //初始化清空队列 num = 0 ; for ( ll i = 1 ; i <= n ; i ++ ) if ( ! InDeg [ i ] ) q . push ( i ) ; //遍历寻找入度为0的点加入队列 while ( ! q . empty ( ) ) { ll now = q . front ( ) ; q . pop ( ) ; num ++ ; //如果该点入度为0,则加入到拓扑序列之中去 for ( ll i = 0 ; i < vec [ now ] . size ( ) ; i ++ ) { if (

拓扑排序

こ雲淡風輕ζ 提交于 2020-02-19 18:56:28
拓扑排序 借鉴 https://blog.csdn.net/qq_38984851/article/details/82844186 拓扑排序的实现步骤 1,在有向图中选一个没有前驱的顶点并且输出 2,从图中删除该顶点和所有以它为尾的弧(白话就是:删除所有和它有关的边) 3,重复上述两步,直至所有顶点输出,或者当前图中不存在无前驱的顶点为止,后者代表我们的有向图是有环的,因此,也可以通过拓扑排序来判断一个图是否有环。 如果我们有如下的一个有向无环图,我们需要对这个图的顶点进行拓扑排序,下图: 首先,我们发现V6和v1是没有前驱的,所以我们就随机选去一个输出,我们先输出V6,删除和V6有关的边,得到如下图结果: 然后,我们继续寻找没有前驱的顶点,发现V1没有前驱,所以输出V1,删除和V1有关的边,得到下图的结果: 然后,我们又发现V4和V3都是没有前驱的,那么我们就随机选取一个顶点输出(具体看你实现的算法和图存储结构),我们输出V4,得到如下图结果: 然后,我们输出没有前驱的顶点V3,得到如下结果: 然后,我们分别输出V5和V2,最后全部顶点输出完成,该图的一个拓扑序列为: v6–>v1—->v4—>v3—>v5—>v2 例题 http://acm.hdu.edu.cn/showproblem.php?pid=1285 完整代码 # include <stdio.h> #

lintcode615. 课程表 拓扑排序

独自空忆成欢 提交于 2020-02-19 06:07:09
现在你总共有 n 门课需要选,记为 0 到 n - 1. 一些课程在修之前需要先修另外的一些课程,比如要学习课程 0 你需要先学习课程 1 ,表示为[0,1] 给定n门课以及他们的先决条件,判断是否可能完成所有课程? 样例 例 1 : 输入 : n = 2 , prerequisites = [ [ 1 , 0 ] ] 输出 : true 例 2 : 输入 : n = 2 , prerequisites = [ [ 1 , 0 ] , [ 0 , 1 ] ] 输出 : false 一段没有想到给出的课程有10000多门而导致超时的代码 class Solution { public : /* * @param numCourses: a total of n courses * @param prerequisites: a list of prerequisite pairs * @return: true if can finish all courses or false */ bool canFinish ( int numCourses , vector < pair < int , int >> & prerequisites ) { // write your code here if ( prerequisites . size ( ) <= 0 ) return

P1113 杂务(拓扑排序)

五迷三道 提交于 2020-02-14 21:57:11
题意: 有n个任务,每个任务完成都有其所需的时间,并且有其前置任务,问完成所有任务要多久(没有直接关系的任务可以同时开始) 思路: 自己写的稍稍有些复杂 首先建图,对于一个任务给所有其前置任务连一条有向边(从前置连向自己),并记录一个点的入读 之前遍历一遍,将入度为0的点加入队列中,边将其所有相邻的点入度减一,如果有入度为0的点,则加入队列中 比较关键的一点就是如何更新时间 dp[nex]=max(dp[nex],dp[i]+tim[nex]) 我的写法较为复杂,还多用了一个队列存时间,用一个DP数组就能直接解决了 #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<cstdio> #include<cstring> #define inf 0x3f3f3f3f using namespace std; const int maxn=1e5+10; queue<int> a,b; vector<int> edge[maxn]; int in[maxn],tim[maxn],ans,n,mx[maxn]; void solve() { for(int i=1;i<=n;i++){ if(!in[i]){ a.push(i),b.push(tim[i]); } } while(

算法 --- 拓扑排序的Java实现

醉酒当歌 提交于 2020-02-13 21:49:14
在一个有向无回路图(AOV网,Activity On Vertex)中找到一个拓扑序列的过程称为拓扑排序。 拓扑序列:图中所有顶点沿着水平线排列而成的一个序列。 拓扑排序的实现步骤:1>从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它; 2>从图中删除该结点,并且删除所有从该结点出发的弧,将这些弧头的入度减1; 3> 重复上述两步,直到所有的顶点都输出。 源码: public class Test { /** 图的顶点信息*/ private static char[] vertexs = {'A','B','C','D','E','F'}; /** 图的顶点的使用情况 */ private static int[] vertexStatus = {0,0,0,0,0,0}; /** 使用邻接矩阵存储图的边信息*/ private static int[][] edges = { {0,1,1,1,0,0}, {0,0,0,0,0,0}, {0,1,0,0,1,0}, {0,0,0,0,1,1}, {0,0,0,0,0,0}, {0,0,0,0,1,0} }; class Stack { private int[] stackList; private int top; public Stack(int length) { stackList = new int

HDU 1285 拓扑排序+优先队列

。_饼干妹妹 提交于 2020-02-12 02:27:47
传送门HDU1285 拓扑排序+优先队列 注意坑点:输入时需要判断重边,否则入度会出错 # include <bits/stdc++.h> using namespace std ; priority_queue < int , vector < int > , greater < int > > q ; //升序优先排列 //priority_queue<int, vector<int >, less<int > >q 为降序排列 //priority<int> q 默认为降序排列 字典序大的为q.top() const int maxn = 510 ; bool G [ maxn ] [ maxn ] ; int in [ maxn ] ; int n , m ; void toposort ( ) { for ( int i = 1 ; i <= n ; i ++ ) if ( in [ i ] == 0 ) q . push ( i ) ; //入度为零压入队列 int c = 1 ; //控制输出格式 while ( ! q . empty ( ) ) { int v = q . top ( ) ; q . pop ( ) ; //取出队列第一个元素并弹出 if ( c != n ) { printf ( "%d " , v ) ; c ++ ; } else

强连通分量之Kosaraju算法

半世苍凉 提交于 2020-02-09 19:41:08
今天学习了强连通分量的Kosaraju算法,网上写的人也不多,但是跟着视频教程讲解,还有去网上搜了博客,感觉他们的讲解都存在一定的问题,我在学习的时候碰到的一些困惑,他们并没有讲的清楚明白,当然,他们说的大致的思路是正确的。 算法思想: 先说说什么是 强连通分量 强连通分量是针对有向图定义的,为了区别无向图的联通分量的概念。在一个强连通分量中,任意两点都相互可达。 这个图中就存在三个强连通分量,分别{0}、{1}、{2},因为这三个点相互不可达,但是自己到自己还是可到达的。 上图就是一个联通分量,应为在这个图中,两两都可达。 观察上面那个强连通分量图,在有向图中就是个环,很明显可以看到,从0->2有条边,但是2不能直接回到0,若2要能回到0必须得找到另外一条路径,就构成了环(自己理解,并无实际证明) 如何求强连通分量的个数呢? 将所有联通分量看成一个点,得到的图一定是有向无环图,若得到的图存在环 红色的边组成的环构成了一个联通分量。 根据这个图,可以看出,如果从出度为0的点进行 深度优先遍历 ,那么一定会在这个顶点所在的联通分量遍历完以后退出。在遍历该联通分量时,不会去遍历其他的联通分量,因为其出度为0。 遍历完0号联通分量后,再遍历1号联通分量,因为1号联通分量出度为1,但是它是指向0号联通分量的,0号刚刚被遍历完,所以遍历完1号联通分量不会跑到其他联通分量中去。 按照这个思路

LeetCode-DFS&Graph-210-M:课程表 II (Course Schedule II )

对着背影说爱祢 提交于 2020-02-06 03:14:15
文章目录 思路 解法 现在你总共有 n 门课需要选,记为 0 到 n-1。 在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量以及它们的先决条件,返回你为了学完所有课程所安排的学习顺序。 可能会有多个正确的顺序,你只要返回一种就可以了。如果不可能完成所有课程,返回一个空数组 示例 1: 输入: 2, [[1,0]] 输出: [0,1] 解释: 总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。 说明: 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。 你可以假定输入的先决条件中没有重复的边。 提示: 这个问题相当于查找一个循环是否存在于有向图中。如果存在循环,则不存在拓扑排序,因此不可能选取所有课程进行学习。 通过 DFS 进行拓扑排序 - 一个关于Coursera的精彩视频教程(21分钟),介绍拓扑排序的基本概念。 拓扑排序也可以通过 BFS 完成。 思路 (1)图论,wait 解法 来源: CSDN 作者: Heroin X 链接: https://blog.csdn.net/Xjheroin/article/details/104180159