时间复杂度O(40n*n)的C++算法:修改图中的边权

news2024/10/6 4:08:28

本篇源码下载

点击下载

1.12.1. 题目
给你一个 n 个节点的 无向带权连通 图,节点编号为 0 到 n - 1 ,再给你一个整数数组 edges ,其中 edges[i] = [ai, bi, wi] 表示节点 ai 和 bi 之间有一条边权为 wi 的边。
部分边的边权为 -1(wi = -1),其他边的边权都为 正 数(wi > 0)。
你需要将所有边权为 -1 的边都修改为范围 [1, 2 * 10^9] 中的 正整数 ,使得从节点 source 到节点 destination 的 最短距离 为整数 target 。如果有 多种 修改方案可以使 source 和 destination 之间的最短距离等于 target ,你可以返回任意一种方案。
如果存在使 source 到 destination 最短距离为 target 的方案,请你按任意顺序返回包含所有边的数组(包括未修改边权的边)。如果不存在这样的方案,请你返回一个 空数组 。
注意:你不能修改一开始边权为正数的边。
1 <= n <= 100
1 <= edges.length <= n * (n - 1) / 2
edges[i].length == 3
0 <= ai, bi < n
wi = -1 或者 1 <= wi <= 107
ai != bi
0 <= source, destination < n
source != destination
1 <= target <= 109
输入的图是连通图,且没有自环和重边。

分析

在这里插入图片描述
在这里插入图片描述

难点分析

任意边的权加1,则任意两点的最短路径要么不变,要么加1。前者对应至少有一条最短路径不经过此边;后者对应所有最短路径都经过此边。首先所有可变权的边,设置为1,每轮选择一条可以加权的权边加1。时间复杂度O(109*边数),时间复杂度太高,改成按顺序处理可变权边,就可以用二分法了,时间复杂度降为O(log(109*边数)约等于O(40)。

时间复杂度

每轮需要寻找最短路径,由于是稠密图,所以用朴素迪氏寻找单源路径。总时间复杂度是:O(log(10^9边数)nn),越O(40100*100)。

大致流程

如果可边权边设置为最大值,如果最短路径小于目标值,返回空。
如果可边权边设置为最小值,如果最短路径大于目标值,返回空。
二分寻找合适的值。

代码讲解

m_vMore0Edge,m_vLess0Edge分别记录不可变权边和可边权边。
CNeiBo3 是封装好的类,用与将权边转成邻接表。
CN2Dis 是封装好的求单源最短路径的类。
Do,求最短路径。
CalLess0Edge将增加的权分配给各边。

核心代码

//朴素迪杰斯特拉算法

class CN2Dis
{
public:
CN2Dis(int iSize) :m_iSize(iSize), DIS(m_vDis), PRE(m_vPre)
{

}
void Cal(int start, const vector<vector<pair<int, int>>>& vNeiB)
{
m_vDis.assign(m_iSize, -1);
m_vPre.assign(m_iSize, -1);
vector vDo(m_iSize);//点是否已处理
auto AddNode = [&](int iNode)
{
//const int iPreNode = m_vPre[iNode];
long long llPreDis = m_vDis[iNode];

  vDo[iNode] = true;
  for (const auto& it : vNeiB[iNode])
  {
    if (vDo[it.first])
    {
      continue;
    }

    if ((-1 == m_vDis[it.first]) || (it.second + llPreDis < m_vDis[it.first]))
    {
      m_vDis[it.first] = it.second + llPreDis;
      m_vPre[it.first] = iNode;
    }
  }

  long long llMinDis = LLONG_MAX;
  int iMinIndex = -1;
  for (int i = 0; i < m_vDis.size(); i++)
  {
    if (vDo[i])
    {
      continue;
    }
    if (-1 == m_vDis[i])
    {
      continue;
    }
    if (m_vDis[i] < llMinDis)
    {
      iMinIndex = i;
      llMinDis = m_vDis[i];
    }
  }
  return (LLONG_MAX == llMinDis) ? -1 : iMinIndex;
};

int next = start;
m_vDis[start] = 0;
while (-1 != (next = AddNode(next)));

}
void Cal(int start, const vector<vector>& mat)
{
m_vDis.assign(m_iSize, LLONG_MAX);
m_vPre.assign(m_iSize, -1);
vector vDo(m_iSize);//点是否已处理
auto AddNode = [&](int iNode)
{
long long llPreDis = m_vDis[iNode];
vDo[iNode] = true;
for (int i = 0; i < m_iSize; i++)
{
if (vDo[i])
{
continue;
}
const long long llCurDis = mat[iNode][i];
if (llCurDis <= 0)
{
continue;
}
m_vDis[i] = min(m_vDis[i], m_vDis[iNode] + llCurDis);
}
long long llMinDis = LLONG_MAX;
int iMinIndex = -1;
for (int i = 0; i < m_iSize; i++)
{
if (vDo[i])
{
continue;
}
if (m_vDis[i] < llMinDis)
{
iMinIndex = i;
llMinDis = m_vDis[i];
}
}
if (LLONG_MAX == llMinDis)
{
return -1;
}

  m_vPre[iMinIndex] = iNode;
  return iMinIndex;
};

int next = start;
m_vDis[start] = 0;
while (-1 != (next = AddNode(next)));

}
const vector& DIS;
const vector& PRE;
private:
const int m_iSize;
vector m_vDis;//各点到起点的最短距离
vector m_vPre;//最短路径的前一点
};

class CNeiBo3
{
public:
CNeiBo3(int n, vector<vector>& edges, bool bDirect, int iBase = 0)
{
m_vNeiB.resize(n);
AddEdges(edges, bDirect, iBase);
}
CNeiBo3(int n)
{
m_vNeiB.resize(n);
}
void AddEdges(vector<vector>& edges, bool bDirect, int iBase = 0)
{
for (const auto& v : edges)
{
m_vNeiB[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);
if (!bDirect)
{
m_vNeiB[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);
}
}
}
vector<vector<std::pair<int,int>>> m_vNeiB;
};

class Solution {
public:
  vector<vector<int>> modifiedGraphEdges(int n, vector<vector<int>>& edges, int source, int destination, int target) {
    m_n = n;
    m_src = source;
    m_dest = destination;
    for (const auto& v : edges)
    {
      if (-1 == v[2])
      {
        m_vLess0Edge.emplace_back(v);
      }
      else
      {
        m_vMore0Edge.emplace_back(v);
      }
    }
    long long left = 0, r = (long long)(1000 * 1000 * 1000-1)* m_vLess0Edge.size()+1;
    while (r - left > 1)
    {
      const auto mid = left + (r - left) / 2;
      const long long ll = Do(mid);
      if ( ll == target )
      {
        m_vLess0Edge.insert(m_vLess0Edge.end(), m_vMore0Edge.begin(), m_vMore0Edge.end());
        return m_vLess0Edge;
      }
      else if (ll > target)
      {
        r = mid;
      }
      else
      {
        left = mid;
      }
    }
    const long long ll = Do(left);
    if (target == ll)
    {
      m_vLess0Edge.insert(m_vLess0Edge.end(), m_vMore0Edge.begin(), m_vMore0Edge.end());
      return m_vLess0Edge;
    }
    return {};
  }
  long long Do(long long llAdd)
  {
    CalLess0Edge(llAdd);
    CNeiBo3 neiBo(m_n);
    neiBo.AddEdges(m_vMore0Edge,false);
    neiBo.AddEdges(m_vLess0Edge, false);
    CN2Dis dis(m_n);
    dis.Cal(m_src, neiBo.m_vNeiB);
    return dis.DIS[m_dest];
  }
  void CalLess0Edge(long long llAdd)
  {
    for (auto& v : m_vLess0Edge)
    {
      const int curAdd = (int)min(llAdd, (long long)1000 * 1000 * 1000 - 1);
      v[2] = 1 + curAdd;
      llAdd -= curAdd;
    }
  }
  int m_n;
  int m_src;
  int m_dest;
  vector<vector<int>> m_vMore0Edge,m_vLess0Edge;
};

测试用例

由于本文篇幅过长,请自行下载测试样例。

其它

视频课程

要是你认为本篇难道较大,不好入手,推荐你先学习基础算法的课程,我已完成部分,余下部分持续更新中,就在CSDN学院。
https://edu.csdn.net/course/detail/38771

C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17

相关下载

如果你想观其大略,建设下载《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

博主想队大家说的话
墨家名称的来源:有所得以墨记之。
闻缺陷则喜的来由:早发现,早修改问题,成本更低
程序是龙,算法是睛

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

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

相关文章

CANoe创建仿真工程

CANoe创建仿真工程 写在前面仿真工程的创建创建工程添加CAN数据库添加系统变量创建面板创建网络节点为节点添加代码工程运行测试总结 写在前面 Canoe的安装不是特别方便&#xff0c;我是参加了松勤的培训课程&#xff0c;不仅需要安装软件还需要安装驱动&#xff0c;刚刚学习的…

YOLOv5算法改进(12)— 主干网络介绍(EfficientNetv2、Swin Transformer和PP-LCNet)

前言:Hello大家好,我是小哥谈。主干网络通常指的是深度学习中的主干模型,通常由多个卷积层和池化层组成,用于提取输入数据的特征。在训练过程中,主干网络的参数会被不断优化以提高模型的准确性。YOLOv5算法中的主干网络可以有多种替换方案,为了后面讲解的方便,本篇文章就…

Neural Improvement Heuristics for Graph Combinatorial Optimization Problems

Neural Improvement Heuristics for Graph Combinatorial Optimization Problems IEEE TRANSACTIONS ON NEURAL NETWORKS AND LEARNING SYSTEMS 2023 摘要 图神经网络&#xff08;GNN&#xff09;架构的最新进展和增加的计算能力已经彻底改变了组合优化&#xff08;CO&#…

Postgresql关于EOH的使用注意

注意通常拿到的指针不是EOH头 EOH是一种扩展数据结构&#xff0c;之前有几篇博客讨论过了&#xff0c;最近在改相关代码加深了一些理解。 EOH目前支持ER_methods、EA_methods两套实现&#xff0c;分别是record类型展开和数组类型展开。 在内存中的样子大概是&#xff08;EA为…

环境下载地址

1. DOTNET环境下载 适用于 Visual Studio 的 .NET SDK 下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/visual-studio-sdks

springboot 智慧图书管理系统

springboot 智慧图书管理系统 liu1113625581

基于springboot实现校园闲置物品租售平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现校园闲置物品租售平台系统演示 摘要 在网络发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;校园商家只能以用户为导向&#xff0c;以产品的持…

本周 AI 新闻报道:多个大厂发布了重大更新

&#x1f525; Adobe Max大会上&#xff0c;Adobe发布了多项使用AI的新功能。其中最重要的是全新的Firefly Image 2图像生成模型&#xff0c;可以生成逼真的人像&#xff1b;Illustrator中的文本到向量图功能&#xff0c;允许通过文字提示生成可编辑的矢量图形&#xff1b;Prem…

RFID技术助力汽车座椅生产

RFID技术助力汽车座椅生产 现在车企越来越多&#xff0c;各种汽车零部件的生产线也激增。库存管理、质量管理、人为错误记录数据是很多工厂的痛点。借助RFID技术能很好的解决一些问题&#xff0c;作为RFID技术厂家的我们也一直致力于解决客户的问题。在汽车座椅的生产线中加入…

力扣 -- 1035. 不相交的线

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {int mnums1.size();int nnums2.size();vector<vector<int>> dp(m1,vector<int>(n1));for(int i…

错误代码 0x80070003

前提&#xff1a; A电脑生成的dll 给 B 电脑用&#xff0c; B调用时出现 错误代码&#xff0c; 关闭后可正常使用 解决办法&#xff1a; A电脑动态链接库 修改配置属性 属性—连接器—调试—生成调试信息—生成经过优化以共享和发布的调试信息 (/DEBUG:FULL) 选择这个即可

mssql还原数据库失败

标题: Microsoft SQL Server Management Studio ------------------------------ 服务器 "192.168.31.132" 的 附加数据库 失败。 (Microsoft.SqlServer.Smo) 有关帮助信息&#xff0c;请单击: https://go.microsoft.com/fwlink?ProdNameMicrosoftSQLServer&…

凉鞋的 Unity 笔记 109. 专题一 小结

109. 专题一 小结 在这一篇&#xff0c;我们来对第一个专题做一个小的总结。 到目前为止&#xff0c;大家应该能够感受到此教程的基调。 内容的难度非常简单&#xff0c;接近于零基础的程度&#xff0c;不过通过这些零基础内容所介绍的通识内容其实是笔者好多年的时间一点点…

打造震撼视觉效果,体验全新After Effects 2024 for Mac/win

想要创作令人惊叹、震撼人心的视觉效果吗&#xff1f;那就来尝试全新的After Effects 2024吧&#xff01;After Effects是业界领先的视觉特效和动画软件&#xff0c;为您提供了无限可能性。无论是电影、广告、视频、网站还是应用程序&#xff0c;After Effects都可以帮助您创建…

统信UOS 1060上通过Fail2Ban来Ban IP

原文链接&#xff1a;统信UOS 1060上通过Fail2Ban来Ban IP hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇在统信UOS 1060上安装Fail2Ban并且当ip被ban后通过邮件发送通知的文章。Fail2Ban 是一个用于防止暴力攻击的开源软件。它可以扫描日志文件&#xff08;例如&a…

深入探索STARK的安全性和可靠性——STARKs全面安全分析

1. 引言 non-interactive STARKs&#xff0c;起源于Interactive Oracle Proofs (IOPs)&#xff0c;然后通过random oracle模式转换为非交互式。StarkWare团队 ethSTARK Documentation – Version 1.2&#xff08;2023年7月&#xff09;论文做了更新&#xff0c;给出了完整具体…

ps提示由于找不到MSVCP140.dll是怎么回事?MSVCP140.dll修复方法

我们的生活和工作都离不开各种软件工具。其中&#xff0c;Adobe Photoshop作为一款专业的图像处理软件&#xff0c;以其强大的功能和广泛的应用领域&#xff0c;受到了广大用户的喜爱。然而&#xff0c;在使用Photoshop的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;…

硬件【11】超全讲解I2C的上拉电阻

文章目录 1.概述2 I2C的上拉电阻3 上拉电阻最小值计算4 上拉电阻最大值计算5 总结 1.概述 相信很多人都清楚&#xff0c;在I2C总线上需要接上拉电阻&#xff1f;但是您针对对I2C上拉电阻足够了解吗&#xff1f;本文带您详细掌握一下I2C的上拉电阻。目录如下&#xff1a; 上拉…

电压放大器在生物医疗中的应用研究

电压放大器是一种常见的电子电路&#xff0c;在生物医疗领域中也得到了广泛应用。其主要作用是将生物信号&#xff08;如心电图、脑电图等&#xff09;转化为电压信号&#xff0c;并将其放大到需要的水平&#xff0c;以便进行分析和处理。 随着生物医学技术的不断发展&#xff…

ARMv7-A 那些事 - 7.栈回溯浅析

By: Ailson Jack Date: 2023.10.14 个人博客&#xff1a;http://www.only2fire.com/ 本文在我博客的地址是&#xff1a;http://www.only2fire.com/archives/159.html&#xff0c;排版更好&#xff0c;便于学习&#xff0c;也可以去我博客逛逛&#xff0c;兴许有你想要的内容呢。…