拓扑排序

拓扑排序

匿名 (未验证) 提交于 2019-12-03 00:18:01
拓扑排序按我的理解就是寻找入度为0的结点(输出或存入数组),将其所有的邻接边都删除。遍历整个图,直至删除完所有结点 删除操作就是看将对应的邻接边的入度减一 基本思想如下: 我用邻接矩阵存储图压缩空间,加快时间 vector<int> Graph[510];//邻接表 int visite[510];//标记结点是否被访问 int cnt[510];//记录每个顶点的入度 int find_indegree(int n)//查找未被访问结点中入度为0的结点 { int i; for(i=1;i<=n;i++) { if(visite[i]==0&&cnt[i]==0) { visite[i]=1; return i; } } return -1; } void TopSort(int n) { int i,j; for(i=0;i<n;i++)//n次循环用来输出n个结点 { int v=find_indegree(n); if(v==-1) cout<<"error"<<endl; else { if(i<n-1)//格式化输出 cout<<v<<" "; else cout<<v<<endl; for(j=0;j<Graph[v].size();j++)//查找当前结点的所有邻接边使其入度减一 cnt[Graph[v][j]]--; } } } 对应基础练习:http://acm

【LeetCode】课程表

匿名 (未验证) 提交于 2019-12-03 00:11:01
【问题】现在你总共有 n 门课需要选,记为 0 到 n-1。 在选修某些课程之前需要一些先修课程。例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习? 示例 1 : 输入: 2 , [[ 1 , 0 ]] 输出: true 解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。所以这是可能的。 示例 2 : 输入: 2 , [[ 1 , 0 ],[ 0 , 1 ]] 输出: false 解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还> 应先完成课程 1 。这是不可能的。 说明: 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。 你可以假定输入的先决条件中没有重复的边。 【思路】由于本题目中的每个课程之间都有相应的联系,因此我们可以根据课程关系来构建一个有向图,如果在这个有向图中存在一个循环,那么则不能学完所有的课程,因为每个课程都需要每个先决条件的课程。一个很简单的思路是使用拓扑排序算法,可以判断一个循环是否存在于一个有向图中。 拓扑排序算法: 计算图中所有节点的入度,如果某些节点的入度为零,则压入到队列todo中,接着循环弹出队列中的节点(即入读为零的节点)

拓扑排序的小总结

匿名 (未验证) 提交于 2019-12-03 00:05:01
#include <iostream> #include <cstdio> #include <cstring> using namespace std ; const int maxn = 100 + 15 ; int n , m , t ; //图中有n个节点 int topo [ maxn ]; //储存拓扑排序的顺序 int staus [ maxn ]; //表示转态 bool Grape [ maxn ][ maxn ]; //表示依赖关系 bool dfs ( int u ) { staus [ u ] = - 1 ; //表示正在进行深搜 for ( int v = 1 ; v <= n ;++ v ) { if ( Grape [ u ][ v ]) { if ( staus [ v ]< 0 ) return false ; //说明存在环 if (! staus [ v ]&&! dfs ( v )) //如果未被访问过 return false ; } } staus [ u ] = 1 ; //表示已经深搜完并返回的状态 topo [-- t ] = u ; return true ; } bool topoSort () { t = n ; memset ( staus , 0 , sizeof ( staus )); //节点都未被访问过 for (

拓扑排序

匿名 (未验证) 提交于 2019-12-02 23:52:01
这篇博客将向大家介绍如何利用拓扑排序判断一个有向图是否有环。 我将向大家展示如何 不用任何STL 完成这道题(主要是忘了怎么用233) 在此特别感谢 张怡和巨佬 的友情帮助(花了一个小时帮我改bug) 废话不多说,正式开始题解 第一步是建树,用邻接表来做 邻接表有四样写法,你知道么 ,这个就不多说了,直接上代码吧,我用的是超级容易错的结构体指针。 struct node{ int v;//指向的节点 node *next;//下一条边 node(){ v=-1; next=NULL; } }*head[1000];//邻接表 void set(){ for(int i=1;i<=n;i++) head[i]=new node; for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; p[y]++; if(head[x]->v==-1){//是空节点 head[x]->v=y; } else{ node *pnew=new node; pnew->v=y; pnew->next=head[x]; head[x]=pnew; }//插入新的节点 } } 然后就是这道题的核心――用拓扑排序判断是否有环了。 首先介绍一下拓扑排序(来自百度百科,可以不看):对一个有向无环图(Directed Acyclic Graph,简称DAG)G进行拓扑排序

TopSort拓扑排序 邻接表 优先队列实现字典序

匿名 (未验证) 提交于 2019-12-02 23:47:01
//TopSort拓扑排序 邻接表 优先队列实现字典序 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> using namespace std; #define inf 0x3f3f3f3f #define why 100005 struct node { int next,to; }a[500005]; int h[why],cnt,n,In[why],ans[why],m; priority_queue<int,vector<int>,greater<int> >q; inline void Add(int x,int y) { cnt++; a[cnt].to=y; a[cnt].next=h[x]; h[x]=cnt; } inline int redn() { int ret=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-')f=-f; ch=getchar(); } while(isdigit(ch)) { ret=ret*10+ch-'0'; ch=getchar(); } return f>0?ret:

Leetcode题解――数据结构之图

匿名 (未验证) 提交于 2019-12-02 23:41:02
二分图 1. 判断是否为二分图 拓扑排序 1. 课程安排的合法性 2. 课程安排的顺序 并查集 1. 冗余连接 二分图 如果可以用两种颜色对图中的节点进行着色,并且保证相邻的节点颜色不同,那么这个图就是二分图。 1. 判断是否为二分图 785. Is Graph Bipartite? (Medium) Input: [[1,3], [0,2], [1,3], [0,2]] Output: true Explanation: The graph looks like this: 0----1 | | | | 3----2 We can divide the vertices into two groups: {0, 2} and {1, 3}. Example 2: Input: [[1,2,3], [0,2], [0,1,3], [0,2]] Output: false Explanation: The graph looks like this: 0----1 | \ | | \ | 3----2 We cannot find a way to divide the set of nodes into two independent subsets. public boolean isBipartite(int[][] graph) { int[] colors = new

家谱树(拓扑排序)

匿名 (未验证) 提交于 2019-12-02 23:40:02
版权声明:转载请注明出处链接 https://blog.csdn.net/qq_43408238/article/details/91392727 【题目描述】 有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。 给出每个人的孩子的信息。 输出一个序列,使得每个人的后辈都比那个人后列出。 【输入】 第1行一个整数N(1≤N≤100),表示家族的人数; 接下来N行,第I行描述第I个人的儿子; 每行最后是0表示描述完毕。 【输出】 输出一个序列,使得每个人的后辈都比那个人后列出; 如果有多解输出任意一解。 【输入样例】 5 0 4 5 1 0 1 0 5 3 0 3 0 【输出样例】 2 4 5 3 1 #include<iostream> #include<vector> #include<string> #include<cstring> #include<cmath> #include<stack> #include <algorithm> #include <stdlib.h> #include <cstdio> #include<sstream> #include<cctype> #include <set> #include<queue> #include <map> #include <iomanip> #define INF 0x3f3f3f3f #define

Cow Traffic(正反向建图+DAG拓扑排序)

﹥>﹥吖頭↗ 提交于 2019-12-02 19:47:00
题意 有N(1<=N<=5000)个点,m条边(1<=M<=50000)。起点可以是任何一个入度为0的点,终点是N。求从起点到终点的所有路中,经过次数最大的一条路。输出经过次数。(规定每个点需要连接到编号更大的点,且不存在循环) 题解 该图为DAG(有向无环图),可利用拓扑排序,正反向建图分别进行两次拓扑排序。 根据乘法原理,在一条边M(u->v)上,通过边M的次数为从源点到达u的方式数量×从终点到达v的方式数量。 Code #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; struct node{ int to,next; }edge1[50005],edge2[50005]; int n,m; int cnt1,head1[5005],indegree1[5005],num1[5005]; int cnt2,head2[5005],indegree2[5005],num2[5005]; void add(int u,int v) { /*正向建图*/ edge1[cnt1].to=v; edge1[cnt1].next=head1[u]; head1[u]=cnt1++; /*反向建图*/ edge2[cnt2].to=u; edge2[cnt2

拓扑排序(poj 1094)

冷暖自知 提交于 2019-12-02 18:46:24
前置知识:拓扑排序 详细注释都在代码里 1 //该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。 2 //是典型的拓扑排序,但输出格式上确有三种形式: 3 4 // 1.该字母序列有序,并依次输出; 5 6 // 2.该序列不能判断是否有序; 7 8 // 3.该序列字母次序之间有矛盾,即有环存在。 9 10 // 而这三种形式的判断是有顺序的:先判断是否有环(3), 11 //再判断是否有序(1),最后才能判断是否能得出结果(2)。 12 //注意:对于(2)必须遍历完整个图,而(1)和(3)一旦得出结果, 13 //对后面的输入就不用做处理了。 14 15 //有一个问题,我不太清楚,就是在确定有序之后,就直接输出答案, 16 //对右面的输入也不再处理,但是后面的输入可以让其成为环的话又就会 17 //让其成为环,所以我想这道题就是在确定有序之后,后面的数据,就都不要了。 18 //应该是这意思把 19 #include<cstdio> 20 #include<algorithm> 21 #include<string.h> 22 #include<math.h> 23 #include<queue> 24 using namespace std; 25 typedef long long ll; 26 const int maxn=1e2+10;

数据结构——图(拓扑排序)

梦想与她 提交于 2019-12-02 15:11:11
一直有听说拓扑排序这个很神奇的算法,一开始总觉得它是类似快排一样的排序算法,今天看了一下,发现并不是这样的。 理解 拓扑排序还是图论中的知识,它是图论中有向图的一种应用,因为有向图中两个节点之间的连接是有头和尾的,不像无向图。所以,我们规定,1:遍历网时,我们顺着一条边往下走的时候,一定是只能从尾走向头,并且只有以某节点为头的所有尾节点都走完的时候,才能继续顺着往下走。2:图中的节点不能成环,也就是说最后输出的顶点数一定要等于总的节点数,少了一个就说明这个网存在环。(其实可以这样子理解,当某节点(活动)的所有先决条件(节点或者叫活动)完成的时候,该节点才能顺利往下走,当网中存在环的时候,可以理解为某个活动完成的以自己完成的为前提的,这就不符合逻辑了)。 拓扑排序算法 所谓的拓扑排序。就是对一张有向图构造拓扑序列的过程,构造时会有“两种”结果,当网点的所有节点都被输出的时候,说明这个图(网)是不存在环的,当输出的节点小于总节点数时,说明这个图(网)是存在的环的。 假定给了一张这样的图 从前面的知识可以知道,对于有向图我们是倾向于用链接链表这样的数据结构的,但是此时我们要在连接链表的基础上增加一个数据位(indata),表示为每个节点的入度。 基本思路:我们从图(网)中选择一个入度为0的顶点输出,并且将该顶点删除,在删除该顶点的时候,需要把以该节点为尾的顶点的入度 减一