首页 > 其他分享 >拓扑排序 专题

拓扑排序 专题

时间:2022-11-29 17:01:10浏览次数:77  
标签:食物链 专题 idx int 拓扑 入度 排序 我们

拓扑排序(\(Topological\) \(sorting\))

拓扑排序指的是有向无环图(\(DAG\));

学过计算机网络的知道计算机网络中有一个拓扑结构;

下面就是一个拓扑结构;

那拓扑序就是,图中任意一对顶点\(u\)和\(v\),若边\(<u,v>∈E(G)\),则\(u\)在线性序列中出现在\(v\)之前

我们可以发现 拓扑序不是唯一的

接下来,我们需要知道一个概念——

对于有向图的某个结点来说,我们把指向它的边的数量叫做入度

从它发出的边的数量称为出度,这个都很好理解吧;

如何获得一个拓扑序:

我们先来找一个 最容易理解的例子,那就是食物链,对一个自然界的食物链来说,一定存在拓扑序;

第一:不存在环

第二:有向

接下来我们来看看如何获得一个拓扑序,我们观察最左面的结点,一定是没有指向它的边,也就是入度为零,最右边的结点呢,是一定不存在它指向别人的边的,如果有,那么它就不是最右边的点也就是出度为零;

那就是说,所有入度为零的点都可以作为起点,我们开一个数组记录入度的值;

至于如何使用邻接表存边,这就不展开解释了,可以参考这个:传送门

其实,拓扑排序也是\(bfs\)的一个简单应用,我们需要 借助队列 来实现;

首先,我们遍历存储入度的数组,获得可以作为起点的结点,将其加入队列;

接下来就可以愉快的遍历了,没当我们遍历到一个点的时候,我们让它的入度--;

这样做的 意义 就是,判断指向这个点的边是不是都遍历过了,因为我们要保证拓扑序最重要的一个特点:\(<u,v>\)的边中,\(u\)一定在\(v\)的前面出现;

如果这个点所有的边都遍历过的话,是不是也就是说这个点已经没有指向它的边了,也就是说这个点可以作为一个起点了,那我们将它加入队列;循环这个操作,知道队列为空;

\(P4017\) 最大食物链计数 - 洛谷

最大食物链数量;最大指的是需要从一个入度为零的点开始到一个出度为零的点,这是一个完整的食物链,问我们给出的食物网中,食物链的数量
① 本题中,不仅需要 记录一下入度 , 还要 记录一下出度,这是因为我们要计算食物链的数量,食物链的最后一个结点,就是出度为零的点
② 食物链的数量,就是一个类似于 数字三角形 求值的\(dp\)问题了

#include <bits/stdc++.h>
using namespace std;

const int N = 5010, M = 500010;
const int INF = 0x3f3f3f3f, MOD = 80112002;

int in[N], out[N], f[N];
int n, m;

//链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void topsort() {
    queue<int> q;

    for (int i = 1; i <= n; i++)
        if (!in[i]) {
            q.push(i);
            f[i] = 1;
        }

    while (q.size()) {
        int u = q.front();
        q.pop();
        for (int i = h[u]; ~i; i = ne[i]) {
            int j = e[i];
            in[j]--;
            f[j] = (f[j] + f[u]) % MOD;
            if (in[j] == 0) q.push(j);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);

    while (m--) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
        in[b]++, out[a]++;
    }

    topsort();

    int res = 0;

    for (int i = 1; i <= n; i++)
        if (!out[i]) res = (res + f[i]) % MOD;

    printf("%d", res);
    return 0;
}

\(P1137\) 旅行计划

这个题,我们根据题意是不是知道这个是一个\(DAG\),我们需要计算的是以城市 \(i\) 为终点最多能够游览多少个城市;这个是不是也是在一个拓扑序上做一个简单的\(dp\)就行了,我们记录一下最大值即可;

#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 2 * N, INF = 0x3f3f3f3f;

int n, m;

//链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

int in[N], f[N];

void topsort() {
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (!in[i]) {
            q.push(i);
            f[i] = 1;
        }

    while (q.size()) {
        int u = q.front();
        q.pop();
        for (int i = h[u]; ~i; i = ne[i]) {
            int j = e[i];
            f[j] = max(f[j], f[u] + 1);
            in[j]--;
            if (in[j] == 0) q.push(j);
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);

    for (int i = 1; i <= m; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
        in[b]++;
    }

    topsort();

    for (int i = 1; i <= n; i++) printf("%d\n", f[i]);

    return 0;
}

标签:食物链,专题,idx,int,拓扑,入度,排序,我们
From: https://www.cnblogs.com/littlehb/p/16935872.html

相关文章

  • Sequelize排序问题: 关联其他表数据的排序实现
    问题描述:有一对多或者多对多的关联表数据要一起提取返回前端时,在没有申明排序规则的情况下,关联的数据的顺序是随机的。在前端多次调用这类接口,会发现,页面展示的关联数据的......
  • 排序实练(1):列表排序-插入法及排序基础认知
    1.1插入法排序:有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——​​插入排序法​......
  • 排序实练(2):列表排序-冒泡法/选择排序/快速排序
    ​​排序算法有很多,包括​​​​插入排序​​​,​​堆排序​​​,​​归并排序​​​,​​选择排序​​​,​​计数排序​​​,​​基数排序​​​,​​桶排序​​​,​​快速排序......
  • acwing113. 特殊排序
    记录交互题这个东西 classSolution{public:vector<int>specialSort(intN){vector<int>res;res.push_back(1);for(inti=2;i<......
  • 5.2.5 快速排序——代码解说
    需思考一个巧妙的办法,在这个数组里头,原地进行这个数组元素倒换,实现参照元素在它该到达的位置去存放,左边的元素都比它小,右边的元素都比它大,不分配动态数组。保证整体左边小,......
  • 5.2.1 归并排序——总体思路
    折半查找快速是因为每次只查一半,另一半不管把一个任务拆成两个部分只完成其中一部分,是一个很有效的办法当元素多了,运算、时间消耗等会比较复杂数组前一半让它有序,后一半......
  • 与堆和堆排序相关的问题
    与堆和堆排序相关的问题作者:Grey原文地址:博客园:与堆和堆排序相关的问题CSDN:与堆和堆排序相关的问题堆结构说明堆结构就是用数组实现的完全二叉树结构,什么是完全二叉......
  • PTA 21级数据结构与算法实验8—排序
    目录7-1统计工龄7-2寻找大富翁7-3点赞狂魔7-4插入排序还是归并排序7-5插入排序还是堆排序7-6逆序对7-7堆排序7-8石子合并7-9第k小7-10快速排序的过程7-1统计工......
  • DataGridView绑定BindingList 中的 DataGridViewCheckBoxColumn 无法点击排序问题
    参考文档DataGridView绑定BindingList<T>带数据排序的类-腾讯云开发者社区-腾讯云(tencent.com) DataGridView使用技巧十三:点击列头实现升序和降序排序-.NET开发......
  • 自然排序
    自然排序      如果数组中部分元素已按自然数顺序排放,例如,数组,则初期自然排好序的子数组段显然有4段,分别为,,和。请充分利用上述特点设计并实现一个自然合并排序算法......