拓扑排序算法

操作对象:AOV网的点和边

有向无环图:有向图且不会形成回路

AOV网:在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,称为AOV网

拓扑排序:在图论中由一个有向无环图的顶点组成的序列中,当且仅当满足以下条件时,称为该图的一个拓扑排序:

1.每个顶点出现且只出现一次

2.若顶点A在序列中排在顶点B的前面,则在图中不存在顶点B到顶点A的路径

拓扑排序的实现

1.从AOV网中选择一个没有前驱的顶点并输出。

2.从网中删除该顶点和所有以它为起点的有向边

3.重复1和2直到当前的AOV网中不存在无前前驱的顶点为止

拓扑排序的实现一般用邻接表来储存图,实现的时间复杂度为O(n+e),一般还需要用一个栈来储存入度为0的点。

个人从题目中发现拓扑排序有点递推的意思。

洛谷 P4017 最大食物链计数

题目背景

你知道食物链吗?Delia 生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条。于是她来就来求助你,然而你也不会啊!写一个程序来帮帮她吧。

题目描述

给你一个食物网,你要求出这个食物网中最大食物链的数量。

(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)

Delia 非常急,所以你只有 1 秒的时间。

由于这个结果可能过大,你只需要输出总数模上80112002 的结果。

输入格式

第一行,两个正整数 n、m,表示生物种类 n 和吃与被吃的关系数 m。

接下来 m 行,每行两个正整数,表示被吃的生物A和吃A的生物B。

输出格式

一行一个整数,为最大食物链数量模上 8011200280112002 的结果。

输入输出样例

输入 #1

5 7
1 2
1 3
2 3
3 5
2 5
4 5
3 4

输出 #1

5

说明/提示

各测试点满足以下约定:

【补充说明】

数据中不会出现环,满足生物学的要求。(感谢 @AKEE )

解题思路

由题目条件知道本题的图是一个有向无环图,1.满足使用拓扑排序的要求,2求路径数,出度为零的点的路径总和就是答案,生产者就是入度为零的点,从删除生产者这个点,生产者这个点会给吃他的那个点提供一条路径,而吃生产者的那个点又会给吃吃生产者的这个点提供一条路径,是不是有点递推的意思了,而拓扑排序在删除入度为零的点就执行这个操作,直到将所有点删除,然后出度为0的点的路径和就是答案

本题我用的是邻接矩阵储存图,当然也可以用邻接表储存

#include<stdio.h>
//book标记出度不为0的点,du数组记录每个点的入度,dp数组记录到每个点i的路径数(生物链数)
int du[5001] = { 0 },  dp[5001], book[5001];
int a[5001][5001];//存储图
int top = 1, queck[50001];//栈存储入度为0的点
int main()
{int i, n, m, x, y;scanf("%d %d", &n, &m);for (i = 1; i <= m; i++){scanf("%d %d", &x, &y);a[x][y] = 1;//x到y这个点有路径du[y]++;//y这个点入度+1book[x] = 1;//标记出度不为0的点}for (i = 1; i <= n; i++)//找到入度为0的点{if (du[i] == 0){queck[++top] = i;dp[i] = 1;//入度为0的点起始算有一条食物链}}while (top > 0)//栈不为空{int k = queck[top];top--;//栈顶出队for (i = 1; i <= n; i++)//遍历k能到的点,{if (a[k][i] == 1)//如果k到i这个点有路径,i吃k{dp[i] = (dp[i] + dp[k]) % 80112002;du[i]--;//删除k这个点使得i这个点的入度减少1if (du[i] == 0)//如果这个点入度为0,入栈queck[++top] = i;a[k][i] = 0;//销毁路径}}}int sum = 0;for (i = 1; i <= n; i++)//统计路径总数if (book[i] == 0)sum = (sum + dp[i]) % 80112002;printf("%d", sum);return 0;
}

用邻接矩阵储存图时,n个点入栈出栈,每一个点遍历n,可知时间复杂度为O(n^2)

洛谷 P1807 最长路

题目描述

设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 G 中 1,n 间的最长路径。

输入格式

输入的第一行有两个整数,分别代表图的点数 n 和边数 m。

第 2 到第 (m+1) 行,每行 3 个整数 u,v,w(u<v),代表存在一条从 u 到 v 边权为 w 的边。

输出格式

输出一行一个整数,代表 1 到 n 的最长路。

若 1 无法到达 n,请输出 −1。

输入输出样例

输入 #1

2 1
1 2 1

输出 #1

1

说明/提示

【数据规模与约定】

  • 对于 20%的数据,n≤100,m≤10^3。
  • 对于 40% 的数据,n≤10^3,m≤10^4。
  • 对于 100% 的数据,1≤n≤1500,0≤m≤5×10^4,1≤u,v≤n,-10^5≤w≤10^5。

 这题两个坑:

1.边权值可能为负数,不适用迪杰斯特拉算法,

2.如果用拓扑排序算法的话需要将不为点不为1且入度为零的点删除而且不是只去除外围一层,而是多层的,原因就是如果你不废除那些除了一之外的入读为零的节点,你如果从一号点开始搜的话,如果那个点有初度,你的一号点所达到的那个点可能就永远都有入度,就永远不可能收入栈

#include<stdio.h>
int u[50001], v[50001], w[50001];//u为起始点,v为终点,w为u->v的权值
int first[1501], next[50001];//first存储每个点的第一条边的位置
int book[1501];
int n, m, sum = 0, flag = 0, max = -1e9;
void dfs(int x)
{book[x] = 1;int k = first[x];while (k != 0){if (book[v[k]] == 0)//值为0代表没有边dfs(v[k]);k = next[k];}
}
int maxs(int x, int y)//max函数返回较大值
{if (x > y)return x;else return y;
}
int qu[1501], top = 0, du[1501], dp[1501];
int main()
{int i;scanf("%d %d", &n, &m);for (i = 1; i <= m; i++){scanf("%d %d %d", &u[i], &v[i], &w[i]);du[v[i]]++;//入度加一//模拟邻接表next[i] = first[u[i]];first[u[i]] = i;}book[1] = 1;//标记1点dfs(1);//dfs搜索if (book[n] == 0)//如果不能到达n{printf("-1");//输出-1return 0;}//清除不为1且入度为0的点for (i = 2; i <= n; i++){if (du[i] == 0)qu[++top] = i;//初始除去1点外的距离为无穷小,因为存在负权边//在取得某点的最长路长度时很有可能是一个负数,如果用0来赋初值的话,// 0会盖过原来正确的长度使得所求值偏大dp[i] = -1e9;}while (top > 0){int k = first[qu[top]];top--;while (k != 0){du[v[k]]--;if (du[v[k]] == 0)qu[++top] = v[k];k = next[k];}}top = 1; qu[1] = 1;//1这个点入栈while (top > 0){int k = first[qu[top]];top--;while (k != 0){du[v[k]]--;dp[v[k]] = maxs(w[k] + dp[u[k]], dp[v[k]]);//求最长路,递推取较大值,if (du[v[k]] == 0)//如果入度减少为零入栈qu[++top] = v[k];k = next[k];}}printf("%d", dp[n]);//输出最长路return 0;
}

本题我用的是模拟邻接表(链式向前星)储存图,拓扑排序算法时间复杂度为O(n+e)

判断1能否到达n采用一次dfs搜索能否将book[n]标记,若能代表能够到达,递推每次取能到达这个点的最大值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/447832.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web3生态系统:构建去中心化的数字社会

随着科技的飞速发展&#xff0c;我们正处在迈向数字未来的道路上&#xff0c;而Web3生态系统则成为这一变革的中心。不仅仅是技术的演进&#xff0c;Web3代表着对传统互联网体系的颠覆&#xff0c;致力于构建一个去中心化的数字社会。本文将深入探讨Web3的核心特征、对金融、社…

2024年美赛A题:资源可用性和性别比例 Resource Availability and Sex Ratios 思路模型代码解析

2024年美赛A题&#xff1a;资源可用性和性别比例 Resource Availability and Sex Ratios 思路模型代码解析 【点击最下方群名片&#xff0c;加入群聊&#xff0c;获取更多思路与代码哦~】 问题翻译 虽然一些动物物种存在于通常的雄性或雌性之外&#xff0c;但大多数物种在很大…

Linux系统Shell脚本-----------正则表达式 文本三剑客之---------grep、 sed

一、正则表达式 1.前言 正则表达式(regular expression)描述了一种字符串匹配的模式&#xff08;pattern&#xff09;&#xff0c;可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。在Linux中也就是代表我们定义的模式模板&…

“错误: 不支持发行版本 XX”的解决方法

目录 1 查看Project Structure 1.1 打开Project Structure 1.2 查看Project Setting/Project 1.3 查看 Project Setting/Modules 1.4 查看Platform Setting/SDKs 2 查看Settings 2.1 打开Settings 2.2 查看Java Compiler 2.3 查看Maven/Runner 3 查看pom.xml 1 查…

AI算力专题:华为算力分拆:全球AI算力的第二极

今天分享的是AI算力系列深度研究报告&#xff1a;《AI算力专题&#xff1a;华为算力分拆&#xff1a;全球AI算力的第二极》。 &#xff08;报告出品方&#xff1a;华西计算机团队&#xff09; 报告共计&#xff1a;53页 全球龙头英伟达业绩持续高度景气&#xff0c;印证全球A…

k8s安装dashboard报错CrashLoopBackOff

报错信息 使用kubectl get pods -A查看集群&#xff0c;出现错误&#xff1a; kubernetes-dashboard kubernetes-dashboard-xxxxxxxxxx6-2qrst 0/1 CrashLoopBackOff 6 15m查看日志后&#xff0c;发现原因&#xff1a; panic: Get "https://10…

架构整洁之道-组件构建原则

5 组件构建原则 大型软件系统的架构过程与建筑物修建很类似&#xff0c;都是由一个个小组件组成的。所以&#xff0c;如果说SOLID原则是用于指导我们如何将砖块砌成墙与房间的&#xff0c;那么组件构建原则就是用来指导我们如何将这些房间组合成房子的。 5.1 组件 组件是软件的…

MySQL索引的原理和SQL优化策略

1. 索引 在InnoDB存储引擎中&#xff0c;索引分为聚簇索引和辅助索引两种类型。 聚簇索引是指基于表的主键构建的索引&#xff0c;它决定了表中数据的物理存储顺序。也就是说&#xff0c;聚簇索引中的键值按照主键的顺序来排序&#xff0c;并且每个叶子节点存储的是整个表行的…

基于SpringBoot Vue超市管理系统

大家好✌&#xff01;我是Dwzun。很高兴你能来阅读我&#xff0c;我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结&#xff0c;还为大家分享优质的实战项目&#xff0c;本人在Java项目开发领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#x…

某赛通电子文档安全管理系统 UploadFileList 任意文件读取漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

离线安装nginx_银河麒麟系统_nginx报错_503_500 Internal Server Error----nginx工作笔记007

如果报这个错误,意思就是,对于nginx.conf文件中指定的,文件夹没有权限 那么这个是去给对应的文件夹赋权限: chmod 777 /opt/module/test_web 就可以了,然后再去访问就不会报错了,还有 503的错误都可以这样解决 然后关于离线安装nginx,尝试了一下如果把之前安装过的nginx,直接…

linux安装二进制openjdk1.8版本【配置永久加载环境变量】

二进制jdk下载地址&#xff1a;https://www.openlogic.com/openjdk-downloads 选择64位 jdk的 java8下载,然后解压 $ cd /home/ec2-user/config/ $ tar xf openlogic-openjdk-8u382-b05-linux-x64.tar.gz $ mv openlogic-openjdk-8u382-b05-linux-x64 openjdk-8编辑环境变…