首页 > 其他分享 >洛谷题单指南-图的基本应用-P1807 最长路

洛谷题单指南-图的基本应用-P1807 最长路

时间:2024-03-28 16:25:03浏览次数:30  
标签:指南 int 洛谷题 拓扑 入度 long P1807 bool 节点

原题链接:https://www.luogu.com.cn/problem/P1807

题意解读:由于对于每一条边u->v,都有u < v,因此节点1的入度一定是0,且是有向无环图,直观上可以通过拓扑排序法搜索每一个节点,计算1到每一个节点的最长距离。但问题在于,入度为0的节点可能不止一个,这样在计算到某个点的最长距离时,会受到其他没有经过1的节点的影响,如下图:

对于左边的情况,很明显,通过拓扑排序可以计算1到2的最长距离为1;

而对于右边的情况,拓扑排序时,先把1、3加入队列,根据1可以确定2的距离为1,根据3又可以把2的距离更新为10,答案就不对了,本质原因是因为3没有经过1,通过3来更新2的距离是不对的,需要想办法排除掉其他入度为0节点对最长距离计算造成的影响。

解题思路:

有两种办法来解决这个问题:

1、从非1的入度为0的节点开始,把他们能经过的所有节点的入度都减1,如果又产生了入度为0的节点,继续进行此操作,这样最终确保拓扑序只能从1开始,再正常使用拓扑排序法来计算1到每个节点的最长路径即可。

100分代码:

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

const int N = 1505;

struct node
{
    int v, w;
};

vector<node> g[N];
queue<int> q;
int in[N]; //每个节点的入度
long long l[N]; //到每一个节点的最长路
int n, m, u, v, w;

bool bfs()
{
    bool success = false;
    for(int i = 1; i <= n; i++) l[i] = -1e10; //l数组元素初始化为负无穷,便于后面的max比较
    l[1] = 0; //节点1的距离是0
    q.push(1); //从1开始进行拓扑排序
    while(q.size())
    {
        int u = q.front(); q.pop();
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i].v, w = g[u][i].w;
            if(--in[v] == 0) q.push(v);
            l[v] = max(l[v], l[u] + w); //到v节点的最长路等于所有到v的路径长度中的最大值
            if(v == n) success = true; //找到节点n,并且是经过1的
        }
    }
    return success;
}

int main()
{
    cin >> n >> m;
    while(m--)
    {
        cin >> u >> v >> w;
        g[u].push_back({v, w});
        in[v]++;
    }
    
    //去除非1入度为0的节点影响
    for(int i = 1; i <= n; i++)
    {
        if(i != 1 && in[i] == 0)
        {
            q.push(i);
        }
    }
    while(q.size())
    {
        int u = q.front(); q.pop();
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i].v;
            if(--in[v] == 0) q.push(v); 
        }
    }
    //从1开始进行拓扑排序,计算每个节点到1的最长距离
    bool res = bfs();
    if(res) cout << l[n];
    else cout << -1;
     
    return 0;
}

2、不必排除掉所有非1的入度为0的节点,正常使用拓扑排序法,要把搜索到的每个点是否经过了1进行标记,只有经过了1到达的点,才进行距离的更新。

100分代码:

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

const int N = 1505;

struct node
{
    int v, w;
};

vector<node> g[N];
queue<int> q;
int in[N]; //每个节点的入度
long long l[N]; //到每一个节点的最长路
bool from1[N]; //每个节点是否是经过1来的
int n, m, u, v, w;

bool bfs()
{
    bool success = false;
    from1[1] = true;
    for(int i = 1; i <= n; i++) l[i] = -1e10; //l数组元素初始化为负无穷,便于后面的max比较
    l[1] = 0; //节点1的距离是0
    for(int i = 1; i <= n; i++)
    {
        if(in[i] == 0)
        {
            q.push(i);
        }
    }
    while(q.size())
    {
        int u = q.front(); q.pop();
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i].v, w = g[u][i].w;
            if(--in[v] == 0) q.push(v);
            if(from1[u]) //只考虑能从1过来的情况,不经过1的不用考虑
            {
                l[v] = max(l[v], l[u] + w); //到v节点的最长路等于所有从1能到v的路径长度中的最大值
                from1[v] = true; //如果前置节点u是从1来的,v也是从1来的
                if(v == n) success = true; //找到节点n,并且是经过1的
            }
        }
    }
    return success;
}

int main()
{
    cin >> n >> m;
    while(m--)
    {
        cin >> u >> v >> w;
        g[u].push_back({v, w});
        in[v]++;
    }
    bool res = bfs();
    if(res) cout << l[n];
    else cout << -1;
     
    return 0;
}

 

标签:指南,int,洛谷题,拓扑,入度,long,P1807,bool,节点
From: https://www.cnblogs.com/jcwy/p/18101977

相关文章

  • Cairo使用指南
    Cairo是一个用于创建矢量图形的开源库,它支持多种操作系统和平台,并提供了丰富的图形绘制功能。以下是Cairo的简单使用指南:环境准备:确保你的开发环境已经安装了Cairo库。根据你的开发语言和平台,可能需要安装相应的Cairo绑定或接口。创建Cairo环境:在使用Cairo进行......
  • 不小心删除的音频文件怎么恢复?不用愁,恢复指南在这里
    在数字化时代,音频文件作为我们珍贵的回忆和资料,有时可能因一时的疏忽或误操作而意外丢失。当您不小心删除了某个重要的音频文件时,不必过于焦虑。本文将为您提供一系列实用的恢复方法,帮助您找回那些误删的音频文件。图片来源于网络,如有侵权请告知一、使用快捷键恢复如果使......
  • 洛谷题单指南-图的基本应用-P4017 最大食物链计数
    原题链接:https://www.luogu.com.cn/problem/P4017题意解读:食物链的顶端不会被其他生物吃,在图结构中设定为入度是0,食物链的底端不会吃其他生物,在图结构式设定为出度是0,此题就是要计算所有入度是0的点到所有出度是0的点一共有多条路径。解题思路:首先,来模拟一样样例,样例数据形成的......
  • 深度学习入门指南:掌握人工智能的未来
    目录前言深度学习基本概念深度学习学习路径必备技能如何选择适合自己的深度学习库深度学习库在处理文本数据方面有哪些优势深度学习技术在未来的发展趋势是什么如何选择适合自己的深度学习课程深度学习在未来的应用场景有哪些深度学习如何帮助我们理解和预测人类语言......
  • 驾御未来:车载系统全方位测试实战指南 02-车机launcher(启动器)
    车载系统全方位测试实战指南02-车机launcher(启动器)文章目录车载系统全方位测试实战指南02-车机launcher(启动器)前言一、车机launcher设计理念二、关键技术剖析1.UI/UX设计:2.语音识别与控制:3.AI算法优化:4.实时性能优化:三、未来发展趋势四、测试设计与策略1.测试......
  • 农村分散式生活污水分质处理及循环利用技术指南
    标准已完成意见征集:本文件给出了农村分散式生活污水分质处理及循环利用的总则、污水收集、污水分质处理、资源化利用、利用模式、运维管理等的指导。本文件适用于农村分散式生活污水分质处理及循环利用的设施新建、扩建和改建工程的设计、施工与运维。注:本文件使用时宜综......
  • Python数据库编程全指南SQLite和MySQL实践
    本文分享自华为云社区《Python数据库编程全指南SQLite和MySQL实践》,作者:柠檬味拥抱。1.安装必要的库首先,我们需要安装Python的数据库驱动程序,以便与SQLite和MySQL进行交互。对于SQLite,Python自带了支持;而对于MySQL,我们需要安装额外的库,如mysql-connector-python。#安装MyS......
  • WinRadius 配置指南
    WinRadius配置指南1RADIUS概述RADIUS是一种用于在需要认证其链接的网络访问服务器(NAS)和共享认证服务器之间进行认证、授权和记帐信息的文档协议。RADIUS在运维审计系统中,主要体现的是认证功能。2设置WinRadius服务器的操作步骤(1)运行WinRadius。在真实计算机上打开软件包......
  • 2024年Java高分面试指南横空出世!1000道面试题+300W字解析
    42、java中有没有指针?43、java中是值传递引用传递?44、实例化数组后,能不能改变数组长度呢?45、假设数组内有5个元素,如果对数组进行反序,该如何做?46、形参与实参区别47、构造方法能不能显式调用?48、什么是方法重载?49、构造方法能不能重写?能不能重载?50、内部类......
  • 使用Docker搭建测试用例管理平台TestLink:简易指南
    简介Testlink是一款免费开源的测试管理软件,基于WEB的测试用例管理系统,主要功能是:测试项目管理、产品需求管理、测试用例管理、测试计划管理、测试用例的创建、管理和执行,并且还提供了统计功能。为了方便快速部署TestLink,并且保持环境的一致性,我们可以使用Docker进行搭建。本文将......