拓扑排序模板(附带题解:有向图的拓扑序列+Fine Logic)

news2024/12/23 7:00:56

目录

应用的问题:

原理解释及性质:

原理:

性质:

解题模板:

模板1:

模板2:

例题:

例题1:有向图的拓扑序列

题目描述:

思路:

代码详解:

例题2:Fine Logic

思路:

解题代码:


应用的问题:

用于解决题目中对于每个点之间具有依赖关系的问题。

(注意该问题所构成的图必须为有向无环图)

例如要满足

A的排名在B前面,A的排名在C前面,B的排名在C前面

这三个条件的排名

于是我们就可以用拓扑排序取解决该问题。

原理解释及性质:

原理:

因为每次选用的都是入度为0的点,就保证的了是将前提已经满足了的点将其入队,按照这个顺序入的队,满足了每个点之间所需要的依赖关系。

性质:

一个有向无环图一定至少存在一个入度为0的点。

解题模板:

模板1:

#include<iostream>
#include<vector>
using namespace std;

const int N=1e5+6;

int d[N];//每个点的入度
vector<vector<int>> access(N);
//对于每个点所指向的点,例如对于access[i][j]表示对于第i个点所指向的第j个点

int main(){ 
    int n,m;
    cin>>n>>m;
    
    int x,y;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        d[y]++;//对每个点的入度进行记录
        access[x].push_back(y);//把y放入x的点中
    }
    
    vector<int> ans;
    for(int i=1;i<=n;i++){
        if(!d[i]) ans.push_back(i);
    }//把所有入度为0的点放入ans中
    
    for(int i=0;i<(int)ans.size();i++)//注意这里必须是ans.size(),因为它是随时变化的
    {
        int cur=ans[i];
        for(auto &nex:access[cur])//遍历第i个点所指向的所有点
        {
            d[nex]--;
            if(!d[nex]) ans.push_back(nex); //ans需要不断放入入度为0的点
        }
    }
    
    
    if((int)ans.size()==n)//遍历完后所有的点都在其中,则代表无环
    {
        for(int i=0;i<n;i++){
            cout<<ans[i]<<" ";//输出拓扑排序后的序列顺序
        }
    }
    else
    {
        printf("有环");
    }
    return 0;
}

模板2:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=100010;
int h[N],e[N],ne[N],idx;
int n,m;
int q[N],d[N];//q表示队列,d表示点的入度

void add(int a,int b)
{
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}

bool topsort()
{
    int hh=0,tt=-1;
    for(int i=1;i<=n;i++)
     if(!d[i]) 
     q[++tt]=i;//将入度为零的点入队
    while(hh<=tt)
    {
        int t=q[hh++];
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            d[j]--;//删除点t指向点j的边
            if(d[j]==0)//如果点j的入度为零了,就将点j入队
            q[++tt]=j;
        }
    }
    return tt==n-1;
    //表示如果n个点都入队了话,那么该图为拓扑图,返回true,否则返回false
}

int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));//初始化
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);//因为是a指向b,所以b点的入度要加1
        d[b]++;
    }
    if(topsort()) 
    {
        for(int i=0;i<n;i++)
        printf("%d ",q[i]);
    }
    else
        printf("有环");

    return 0;
}

例题:

例题1:有向图的拓扑序列

题目描述:

思路:

模板题,直接套板子

代码详解:

#include<iostream>
#include<vector>
using namespace std;

const int N=1e5+6;

int d[N];//每个点的入度
vector<vector<int>> access(N);
//对于每个点所指向的点,例如对于access[i][j]表示对于第i个点所指向的第j个点

int main(){ 
    int n,m;
    cin>>n>>m;
    
    int x,y;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        d[y]++;//对每个点的入度进行记录
        access[x].push_back(y);//把y放入x的点中
    }
    
    vector<int> ans;
    for(int i=1;i<=n;i++){
        if(!d[i]) ans.push_back(i);
    }//把所有入度为0的点放入ans中
    
    for(int i=0;i<(int)ans.size();i++)//注意这里必须是ans.size(),因为它是随时变化的
    {
        int cur=ans[i];
        for(auto &nex:access[cur])//遍历第i个点所指向的所有点
        {
            d[nex]--;
            if(!d[nex]) ans.push_back(nex); //ans需要不断放入入度为0的点
        }
    }
    
    
    if((int)ans.size()==n)//遍历完后所有的点都在其中,则代表无环
    {
        for(int i=0;i<n;i++){
            cout<<ans[i]<<" ";//输出拓扑排序后的序列顺序
        }
    }
    else
    {
        printf("有环");
    }
    return 0;
}

例题2:Fine Logic

题目描述:

思路:

当构成的图为有向无环图的时候,拓扑排序即为正解。

当构成的图为有向有环图的时候,输出1到n,以及n到1即为正解(原因:对于这两组解已经包括了所有的可能的情况,则直接输出即可。例如对于1、2、3、4、5。以及5、4、3、2、1。我们取2看,对于第一个2它包括了大于3、4、5的情况,对于第二个2它包括了大于1的情况。我们总的来看即包含2的所有情况。对于每个数都是一样,故该答案为正解)

解题代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1000010;
int h[N],e[N],ne[N],idx;
int n,m;
int q[N],d[N];//q表示队列,d表示点的入度

void add(int a,int b)
{
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}

bool topsort()
{
    int hh=0,tt=-1;
    for(int i=1;i<=n;i++)
     if(!d[i]) 
     q[++tt]=i;//将入度为零的点入队
    while(hh<=tt)
    {
        int t=q[hh++];
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            d[j]--;//删除点t指向点j的边
            if(d[j]==0)//如果点j的入度为零了,就将点j入队
            q[++tt]=j;
        }
    }
    return tt==n-1;
    //表示如果n个点都入队了话,那么该图为拓扑图,返回true,否则返回false
}

int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));//如果程序时间溢出,就是没有加上这一句
    for(int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);//因为是a指向b,所以b点的入度要加1
        d[b]++;
    }
    if(topsort()) 
    {
        cout<<"1\n";
        for(int i=0;i<n;i++)
        printf("%d ",q[i]);
        //经上方循环可以发现队列中的点的次序就是拓扑序列
        //注:拓扑序列的答案并不唯一,可以从解析中找到解释
        puts("");
    }
    else{
        cout<<"2\n";
        for(int i=1;i<=n;i++){
            cout<<i<<" ";
        }
        cout<<endl;
        for(int i=n;i>=1;i--){
            cout<<i<<" ";
        }
    }
    

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】文件描述符及重定向

目录 文件描述符的引入 什么是文件描述符 文件描述符的分配规则 重定向 输出重定向 输入重定向 追加重定向 dup2() 文件描述符的引入 上一章&#xff0c;我们讲解了系统接口&#xff0c;了解了open()函数的返回值是一个整数.那么这个整数究竟是什么呢&#xff1f;我们可…

非Spring环境 | Mybatis-Plus插入数据返回主键两种方式(注解或XML)

废话不多说&#xff0c;直接撸代码: <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace&qu…

vr海上安全作业模拟培训软件降低风险隐患

VR虚拟现实技术在军事训练中的应用越来越广泛。其中&#xff0c;将VR技术应用到出海安全知识教育培训中&#xff0c;可以有效地提高学员的安全知识和技能水平&#xff0c;降低实际操作中的风险。以下是VR出海安全知识教育培训的价值。 VR技术是一种利用计算机生成的虚拟环境来模…

【SpirngCloud】分布式事务解决方案

【SpirngCloud】分布式事务解决方案 文章目录 【SpirngCloud】分布式事务解决方案1. 理论基础1.1 CAP 理论1.2 BASE 理论1.3 分布式事务模型 2. Seata 架构2.1 项目引入 Seata 3. 强一致性分布式事务解决方案3.1 XA 模式3.1.1 seata的XA模式3.1.2 XA 模式实践3.1.3 总结 4. 最终…

ARP协议(地址解析协议)

文章目录 ARP协议&#xff08;地址解析协议&#xff09;MAC地址ARP协议ARP具体实现同一链路不同链路 ARP 缓存缓存查询 APR请求/响应报文 ARP协议&#xff08;地址解析协议&#xff09; MAC地址 MAC 地址的全称是 Media Access Control Address&#xff0c;即媒体访问控制地址…

全网最细,时序数据库InfluxDB详解,你不知道的都在这...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 直接上图片&#…

新一代信息技术浪潮下的DPU力量 中科驭数亮相2023中国互联网大会

7月18日&#xff0c;由中国互联网协会主办&#xff0c;北京经济技术开发区管委会、北京市通信管理局、工业和信息化部新闻宣传中心联合主办的2023&#xff08;第二十二届&#xff09;中国互联网大会如约而至&#xff01;中科驭数出席本次大会&#xff0c;高级副总裁张宇应邀在新…

Python内置函数系统学习(3)——数据转换与计算(详细语法参考 + 参数说明 + 具体示例)详解 min()函数 | lambda 真的牛啊

两岸猿声啼不住&#xff0c;轻舟已过万重山&#xff01; &#x1f3af;作者主页&#xff1a; 追光者♂&#x1f525; &#x1f338;个人简介&#xff1a; &#x1f496;[1] 计算机专业硕士研究生&#x1f496; &#x1f31f;[2] 2022年度博客之星人工智能领域TOP4&#x1f…

java项目之社区生活超市管理系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的社区生活超市管理系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(7 月 25 日论文合集)

文章目录 一、Automotive Object Detection via Learning Sparse Events by Temporal Dynamics of Spiking Neurons1.2 Exposing the Troublemakers in Described Object Detection1.3 AMAE: Adaptation of Pre-Trained Masked Autoencoder for Dual-Distribution Anomaly Dete…

【档案专题】四、电子档案形成与收集

导读&#xff1a;主要针对电子档案形成与收集相关内容介绍。对从事电子档案管理信息化的职业而言&#xff0c;不断夯实电子档案管理相关理论基础是十分重要。只有通过不断梳理相关知识体系和在实际工作当中应用实践&#xff0c;才能走出一条专业化加职业化的道路&#xff0c;从…

25.4 matlab里面的10中优化方法介绍——最速下降法(matlab程序)

1.简述 matlab实现最速下降法 定义&#xff1a;沿负梯度方向进行搜索的算法&#xff08;负梯度方向为最速下降方向&#xff09; 算法步骤&#xff1a; 步0&#xff1a;选取初始点x0&#xff0c;容许误差是e[0~1],令k1 步1&#xff1a;计算目标函数的梯度gk▽f(xk)) 若 ||g…

网工内推 | 初级网工、Linux运维,IP证书优先

01 光联世纪 招聘岗位&#xff1a;初级网络工程师 职责描述&#xff1a; 1.负责日常基础网络运维工作&#xff1b; 2.负责日常网络监控工作&#xff1b; 3.负责现场基础技术支持工作&#xff1b; 4.主动进行自我迭代&#xff0c;不断提升技术能力和个人素质。 任职要求&#x…

行为型模式 - 观察者模式

概述 定义&#xff1a; 又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时&#xff0c;会通知所有的观察者对象&#xff0c;使他们能够…

jQuery的DOM操作之笔记总结

jQuery的DOM操作之笔记总结 首先我们来介绍一下什么是DOM 简述&#xff1a; 1.DOM全称Document Object Model&#xff08;文档对象模型&#xff09;。 2.每个文档都是一棵DOM结构的树&#xff0c;文档里的很多元素&#xff0c;就像树上的很多节点&#xff0c;或是分叉的树枝…

【Git】git仓库完整迁移

代码仓库&#xff0c;在公司有两个团队在做&#xff0c;并且gitlab所在环境不互通。有一个团队做的时间久一点&#xff0c;另一个团队想要用并做一些定制。就需要将代码转移到另一个gitlab管理。 参考&#xff1a;【Git】git仓库完整迁移&#xff08;代码&#xff0c;分支&…

ubuntu挂载ext4文件系统

文章目录 1.虚拟机分配10G磁盘用来挂载ext4文件系统2.磁盘分区3.创建文件系统4.挂载文件系统5.卸载文件系统6.使用ior测试ext4三种日志模式&#xff08;1&#xff09;ordered&#xff08;2&#xff09;journal&#xff08;3&#xff09;writeback 1.虚拟机分配10G磁盘用来挂载e…

编码类型 ASCII URLcode编码 Unicode编码 utf编码理解

编码类型 ASCII URLcode编码 Unicode编码 utf编码理解 bin是二进制 oct是八进制 hex是16进制 Ord()检测ASCII码&#xff0c;python3也可查中文 HTML实体编码能被html页面解析&#xff0c;使用ord&#xff08;&#xff09;对单个字符查看转换后结果&#xff0c;字母就是ASCII…

B2B2C开源多语言多商户跨境外贸网站部署开发

随着全球化的发展&#xff0c;跨境外贸成为了许多企业拓展业务的重要方向。搭建一个B2B2C开源多语言多商户跨境外贸网站&#xff0c;将有助于实现企业的全球化经营。那么&#xff0c;如何搭建一个B2B2C跨境外贸网站呢&#xff1f; 一、选择合适的开源平台 在搭建一个B2B2C跨境…

【设计模式】单例设计模式详解(包含并发、JVM)

文章目录 1、背景2、单例模式3、代码实现1、第一种实现&#xff08;饿汉式&#xff09;为什么属性都是static的&#xff1f;2、第二种实现&#xff08;懒汉式&#xff0c;线程不安全&#xff09;3、第三种实现&#xff08;懒汉式&#xff0c;线程安全&#xff09;4、第四种实现…