拓朴排序与动态规划

2024-03-21 08:40
文章标签 动态 规划 排序 拓朴

本文主要是介绍拓朴排序与动态规划,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、知识部分

1 概念

如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。
拓扑排序指是将一个DAG图中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边 < u , v > ∈ E ( g ) \lt u,v\gt \in E(g) <u,v>∈E(g),则u在线性序列中出现在v之前。

2 实现

Step 1:选择一个入度为0的点输出;
Step2:删除此节点及其所有出边;
Step3:重复执行1,2,直至图空。
例:
原图:

输出0。

输出1。
在这里插入图片描述
输出3

输出2。

输出4。
此时图空了,拓扑序列为0,1,3,2,4

2.1 使用BFS

首先将入度为0的顶点入队;
while(队列不空){队头的所有邻接点入度-1;如果存在邻接点入度变为0时则入队;出队;
}
出队序列就是拓扑序列;

这样得到的拓扑序列不唯一。那如何使拓扑序列的字典序最小呢?
将队列替换为优先队列

2.2 使用DFS

每次都沿着一条路径一直向下搜索,直到某个顶点出度为0被标记已经访问,就停止递归,往回走,在回来的路上记录拓扑排序,即后序遍历。(所以我们得到的序列的反着的,反转一下就好了)

二、实践

1 家谱树

1.1 题目描述

请你整理一下一个家谱。 给出每个人的孩子的信息。 输出一个序列,使得每个人的后辈都比那个人后列出。
第1行一个整数 N ( 1 ≤ N ≤ 100 ) N(1 \le N \le 100) N(1N100) ,表示家族的人数; 接下来 N N N 行,第 I I I 行描述第 I I I 个人的儿子; 每行最后是0表示描述完毕。
如果有多解输出字典序最小的解。

1.2 思路

字典序最小,使用优先队列。
用vector更简洁。

1.3 AC代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("___OK___")
#define pr printf("\n")
#define pa printf("A: ")
#define pi acos(-1.0)
using namespace std;
priority_queue<int,vector<int>,greater<int> > q;
int n;
vector<vector<int> >e(1000);
int d[1002];
void bfs(){//入队for(int i=1;i<=n;i++){if(d[i]==0){q.push(i);}}while(!q.empty()){ll k=q.top();q.pop();printf("%d ",k);for(int i=0;i<e[k].size();i++){d[e[k][i]]--;//队头的所有邻接点入度--if(!d[e[k][i]]){q.push(e[k][i]);}}}
}
int main(){scanf("%d",&n);for(int i=1;i<=n;i++){int x;while(scanf("%d",&x)&&x!=0){//i到x有一条边e[i].push_back(x);d[x]++;//记录每个点的入度}}bfs();return 0;
}

2 食物链2

2.1 题目描述

现在给你 n n n 个物种和 m m m 条能量流动关系,求其中的食物链条数。物种的名称为从 1 1 1 n n n 编号 M M M 条能量流动关系形如 a 1 , b 1 , a 2 , b 2 , a 3 , b 3 , … , a m − 1 , b m − 1 , a m , b m a_1,b_1,a_2,b_2,a_3,b_3,\ldots,a_{m-1},b_{m-1},a_m,b_m a1,b1,a2,b2,a3,b3,,am1,bm1,am,bm。其中 a i a_i ai b i b_i bi 表示能量从物种 a i a_i ai 流向物种 b i b_i bi,注意单独的一种孤立生物不算一条食物链。

2.2 思路

入度为零的点的方案数为1,其余的点的方案数等于指向它的点的方案数之和,最后统计出度为0的点的方案数,累加即可。
此时用了一点点DP。
注意到单独的一种孤立生物不算一条食物链,那么在一开始入度为零的点进入队列时要判断一下,不让那些没有出度的点进入队列。

2.3 AC代码

#include<bits/stdc++.h>
#define ll long long
#define bug printf("___OK___")
#define pr printf("\n")
#define pa printf("A: ")
#define pi acos(-1.0)
using namespace std;
const int N=1000010;
ll n,m,f[N],d[N];
vector<ll> e[N];
ll ans;
ll bfs(){queue<ll> q;for(int i=1;i<=n;i++){if(!d[i]&&e[i].size()){q.push(i);f[i]=1; }}	while(!q.empty()){ll x=q.front();q.pop();if(!e[x].size()){ans+=f[x];}for(int i=0;i<e[x].size();i++){ll t=e[x][i];f[t]+=f[x];d[t]--;if(!d[t]){q.push(t);}}}return ans;
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){ll x,y;cin>>x>>y;d[y]++;e[x].push_back(y);}cout<<bfs();return 0;
}

这篇关于拓朴排序与动态规划的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/832246

相关文章

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节