图论排序---拓扑排序

定义

对于有向无权无环图,进行拓扑排序

实现方式

  • Kahn算法
  • 基于DFS的拓扑排序算法

Kahn算法

优化前时间复杂度O(\(n^{2}\))

排序的过程

1.对于DAG,先输出没有前驱的点
2.把与前驱相关的边删除
3.继续输出没有前驱的点
4.重复前者,直到DAG为空或者没有前驱

如果我们有如下的一个有向无环图,我们需要对这个图的顶点进行拓扑排序,过程如下:

首先,我们发现V6和v1是没有前驱的,所以我们就随机选去一个输出,我们先输出V6,删除和V6有关的边,得到如下图结果:

然后,我们继续寻找没有前驱的顶点,发现V1没有前驱,所以输出V1,删除和V1有关的边,得到下图的结果:

然后,我们又发现V4和V3都是没有前驱的,那么我们就随机选取一个顶点输出(具体看你实现的算法和图存储结构),我们输出V4,得到如下图结果:

然后,我们输出没有前驱的顶点V3,得到如下结果:

然后,我们分别输出V5和V2,最后全部顶点输出完成,该图的一个拓扑序列为:
v6–>v1—->v4—>v3—>v5—>v2

应用

给出n个点,m个关系
再给出u,v,表示u比v厉害
然后进行排序

邻接矩阵版Kahn算法的拓扑排序

复杂度O(\(n^{2}\))
传送门
裸拓扑排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N=510;
std::vector<int> v;
int g[N][N];
int degree[N];
int n;
void init(){
    memset(g,0,sizeof(g));
    v.clear();
    memset(degree,0,sizeof(degree));
}
void topological_sort(){
    for(int i=1;i<=n;i++){
        int k;//假设无环
        for(int j=1;j<=n;j++){
            if(degree[j]==0){//找到一个入度为0的点
                degree[j]--;//标记为-1,防止下一次循环的时候还会访问到这个点
                k=j;
                v.push_back(j);
                break;
            }
        }
        for(int j=1;j<=n;j++){//从点k出发到达的点都给取消掉,把j的入度减1
            if(g[k][j]==1)degree[j]--;
        }
    }
}
void print(){
    printf("%d",v[0]);
    for(int i=1;i<v.size();i++){
        printf(" %d",v[i]);
    }
    putchar('\n');
}
int main(){
    int m;
    while(~scanf("%d%d",&n,&m)){
        init();
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            if(g[u][v]==0){//去重边,防止入度混乱
                g[u][v]=1;
                degree[v]++;
            }
        }
        topological_sort();
        print();
    }
    return 0;
}

邻接表版Kahn算法拓扑排序

vector

结构体

原文地址:https://www.cnblogs.com/Emcikem/p/11528898.html

时间: 2024-10-14 13:06:52

图论排序---拓扑排序的相关文章

【图论】拓扑排序应用

拓扑排序虽是一种排序,但是它跟平时所接触的sort或者qsort不同,排序的意义不同.拓扑排序针对有向无回路图(DAG)而言的,不应用与存在回路的有向图. [图论]广度优先搜索和深度优先搜索 有说到了BFS和DFS,拓扑排序是DFS的一个应用. 有向无回路图能说明事件的发生的先后的顺序.比如穿衣服,士兵排队等.一个具体的例子,有N个物体,下面给出物体的重量比较,比如(a,b)表示a比b重等等,问已给出的条件是否会矛盾?其实就是判断用所给条件所组织的一个图中是否会存在环? 在DFS中加入时间戳,完

数据结构:图论:拓扑排序! 两种方法!

拓扑排序:(1)由偏序变成全序的过程!直观的说,偏序指集合中仅有部分成员之间可比较!而全序指集合中全体成员之间均可比较! (2)将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前. 数据结构中进行拓扑排序的方法: 方法一: (1)在有向图中选一个没有前驱的顶点且输出之! (2)从图中删除该顶点和所有以它为尾的弧. (3)重复上述两部,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止.后一种情况说明有向图中存在环! 代码: #

图论之拓扑排序 poj 2367 Genealogical tree

题目链接 http://poj.org/problem?id=2367 题意就是给定一系列关系,按这些关系拓扑排序. #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<algorithm> using namespace std; const int maxn=200; int ans; int n; int in[maxn]; //记录入度

图论_拓扑排序

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前. 通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列.简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序. 执行步骤 由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止. (1) 选

python 排序 拓扑排序

在计算机科学领域中,有向图的拓扑排序是其顶点的先行排序,对于每个从顶点u到顶点v的有向边uv,在排序的结果中u都在v之前. 如果图是有向无环图,则拓扑排序是可能的(为什么不说一定呢?) 任何DAG具有至少一个拓扑排序,并且这些已知算法用于在线性时间内构建任何DAG的拓扑排序 图论:是组合数学的一个分支,它和其他分支比如:群论.拓扑学.矩阵论有着密切的关系.图是图论的主要研究对象.图是由若干给定的顶点以及连接两定点的变构成的图形,这些图形通常用来描述某些事物间的某种特定关系.顶点用于代表事物,而顶

图论_拓扑排序_练习1(优先队列小顶堆)

priority_queue 基本操作: empty()   如果队列为空,则返回真 pop() 删除对顶元素,删除第一个元素 push()     加入一个元素 size()  返回优先队列中拥有的元素个数 top() 返回优先队列队顶元素,返回优先队列中有最高优先级的元素( #队列中为front() ) back()             返回优先队列队尾元素,返回优先队列中有最低优先级的元素 在默认的优先队列中,优先级高的先出队.在默认的int型中先出队的为较大的数. priority_

luogu1347 排序 (拓扑排序)

题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序. 输入输出格式 输入格式: 第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示.m表示将给出的形如A<B的关系的数量. 接下来有m行,每行有3个字符,分别为一个大写

洛谷P1137 旅行计划 拓扑排序 图论

洛谷P1137 旅行计划 拓扑排序   图论在拓扑排序中把每个点能够浏览的点加上去 但是这样会有重复 因为我们要求一个点向前多能浏览的点 所以我们只要求连向这个点中能向前浏览的点数最多的点这一路就是能浏览的最多的点 然后这个点就相当于是拓扑排序中使该点的入度为 0 的那个点用那个点来更新当前点就行了 1 #include <bits/stdc++.h> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 #define LL long long 4

图论基础——邻接链表存图+拓扑排序

邻接链表存图,在这里其实是用数组进行模拟的 又叫做链式存储法,本来是要用链表实现的,但大多数情况下只需要用数组模拟即可 例: u(边的起点) v(边的终点) w(边的权值) 4 2 1 1 2 3 1 4 1 1 5 2 4 3 4 2 3 1 话不多说,直接上代码 for(int i=1;i<=m;i++) { scanf("%d%d%d",&u1,&v1,&w1); e[i].u =u1;//赋给第i条边的起点 e[i].v =v1;//赋给第i条边的