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

拓扑排序 专题

时间:2022-12-05 12:32:09浏览次数:66  
标签:食物链 专题 idx int 拓扑 入度 ne 排序

拓扑排序(\(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,拓扑,入度,ne,排序
From: https://blog.51cto.com/u_3044148/5911897

相关文章

  • js多个(N)个数组的的元素组合排序算法,多维数组的排列组合或多个数组之间的排列组合
    现在有一批手机,其中颜色有['白色','黑色','金色','粉红色'];内存大小有['16G','32G','64G','128G'],版本有['移动','联通','电信'],要求写一个算法,实现[['白色','16G','移动'......
  • 数组排序,自己内部会调整,数组也是引用类型
    Java的基本数据类型有8种,分别是:byte(位)、short(短整数)、int(整数)、long(长整数)、float(单精度)、double(双精度)、char(字符)和boolean(布尔值)。数组是引用类型 int[] arr2 = {......
  • golang的快速排序
    1、什么是快速排序:快速排序是一种分治策略的排序算法,本质上来看,快速排序是对冒泡排序的一种改进,属于交换类的排序算法。是由英国计算机科学家 TonyHoare​ 发明的,该算法......
  • #yyds干货盘点# 名企真题专题: 连续最大和
    1.简述:描述一个数组有N个元素,求连续子数组的最大和。例如:[-1,2,1],和最大的连续子数组为[2,1],其和为3输入描述:输入为两行。第一行一个整数n(1<=n<=100000),表示一共......
  • 排序简介
    排序的概念及其运用排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。稳定性:假定在待排序的记录序列中,存在多个具有相同的关键......
  • 排序算法:快速排序
    简介快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个项目要Ο(nlogn)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排......
  • 排序算法:比较排序
    算法简介:排序排序是一个非常经典的问题,它以特定顺序(递增、非递减(递增或扁平))对数组(或列表)的项目(可以比较,例如整数、浮点数、字符串等)进行重新排序)、递减、非递增(递减或平......
  • 排序算法:非比较排序
    堆排序voidAdjustDown(int*arr,intsz,introot)//向下调整{ intparent=root; intchild=root*2+1; while(child<sz) { if(child+1<sz&&ar......
  • 排序算法:归并排序
    递归实现void_MergeSort(int*arr,intleft,intright,int*tmp){ if(left>=right) return; intmid=left+(right-left)/2; _MergeSort(arr,left,......
  • 排序链表 重排链表 最接近目标价格的甜点成本 环形链表
    148.排序链表弄到数组里,数组排序,再弄个新链表Listlist=newArrayList<>();ListNodepre=head;while(pre!=null){list.add(pre.val);pre=pre.next;}int[......