当前位置: 首页 > news >正文

【最短路问题转换/拓扑排序+dp】P1807 最长路

题目

P1807 最长路

分析

两种做法:

  • 将“最长路问题”转化“最短路问题”,在存入边长的时候存相反数即可,最后得到的结果再取相反数就得到了最长路径。时间复杂度为O(n*m)。
    请添加图片描述
    如何让最短路算法选择路径较长的1->2->3->5这条路呢?我们可以将边权存成对应的相反数,那么本身越大的路径就变得越小了,按照最短路算法选择目前最短的路径,再取相反数就是我们原本要求的最长路径。因为涉及负数路径,所以我们只能使用bf或者spfa。

  • 由于本题要求的是1号结点到第n号结点之间的最长路径,而结点总个数就是1~n个,所以1号结点的入度为0,n号结点的出度为0,正好可以用拓扑排序按照1号结点到n号结点的方向对路径进行研究,不断取最大值,这就是dp的过程。时间复杂度为O(n+m)。
    细节问题:
    请添加图片描述
    我们要求的是从1到n的最长路,而实际在求最长路的时候,其他入度为0的结点会影响从1到n的结果。所以我们先对除1以外的所有入度为0的结点做一次拓扑排序,将这些可能干扰结果的路线全部砍掉以后,再对1号结点做拓扑排序。

代码

方法1:

//bf算法
#include<iostream>
#include<vector>
#include<cstring>using namespace std;const int N = 1510, INF = 0x3f3f3f3f;typedef pair<int,int> PII;vector<PII> edge[N];int n,m,dist[N],s; //每次找最短边长,经过n-1次更新就可以找到所有点的最短路径 
void bf()
{memset(dist,0x3f,sizeof dist); //dist初始化为无穷dist[s] = 0;bool flag = false;//最多执行n-1次,就可以确定所有最短路的边。如果有一次操作没有任何relax,就提前结束 for(int i=1;i<n;i++){flag = false;//对图上每一条边进行relax  for(int u=1;u<=n;u++){for(auto& t:edge[u]){int v = t.first, w = t.second;if(dist[u] + w < dist[v]) //s->u->v的距离小于s->v的距离就更新dist[v] {dist[v] = dist[u] + w;flag = true;}}}	if(!flag) break;	}		
}int main()
{cin >> n >> m;s = 1;for(int i=1;i<=m;i++){int u,v,w;cin >> u >> v >> w;edge[u].push_back({v,-w}); //有向边,存相反数 }bf();if(dist[n] == INF) cout << -1 << endl;else cout << -dist[n] << endl;return 0;
} 
//spfa
//在bf的基础上用队列优化,将relax过的结点加入队列,并打上标记。直到队列为空结束。 
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>using namespace std;typedef pair<int,int> PII;const int N = 1510, INF = 0x3f3f3f3f;vector<PII> edge[N];int n,m,s,dist[N];bool st[N];void spfa()
{memset(dist,0x3f,sizeof dist);dist[s] = 0;queue<int> q;q.push(s);st[s] = true;while(q.size()){int u = q.front(); q.pop();st[u] = false; //出队取消标记!!! for(auto& t:edge[u]){int v = t.first, w = t.second;if(dist[u] + w < dist[v]){dist[v] = dist[u] + w;//因为v发生relax了,把v放入队列并打上标记 if(!st[v]) //一定要检查v是否已经在队列中了!!! {q.push(v);st[v] = true;} }}}
}int main()
{cin >> n >> m;s = 1;for(int i=1;i<=m;i++){int u,v,w; cin >> u >> v >> w;edge[u].push_back({v,-w}); }spfa();if(dist[n] == INF) cout << -1 << endl;else cout << -dist[n] << endl;return 0;
}

方法2:

先看错误代码,没有消除其他入度为0的点的路线

#include<iostream>
#include<vector>
#include<queue>using namespace std;typedef pair<int,int> PII;const int N = 1510;vector<PII> edge[N];int n,m,s,in[N],f[N]; //f[i]:表示从1到i走过的最长路 int main()
{cin >> n >> m;s = 1;for(int i=1;i<=m;i++){int u,v,w; cin >> u >> v >> w;edge[u].push_back({v,w}); in[v]++;}//拓扑排序queue<int> q;//先把所有入度为0的结点加入队列 for(int i=1;i<=n;i++){if(in[i] == 0) q.push(i);f[i] = -1e9;}while(q.size()){int u = q.front(); q.pop();for(auto& t:edge[u]){int v = t.first, w = t.second;in[v]--;f[v] = max(f[v], f[u] + w);if(in[v] == 0) q.push(v);}}if(f[n] == -1e9) cout << -1 << endl;else cout << f[n] << endl;return 0;
}

正确代码:

#include<iostream>
#include<vector>
#include<queue>using namespace std;typedef pair<int,int> PII;const int N = 1510;vector<PII> edge[N];int n,m,s,in[N],f[N]; //f[i]:表示从1到i走过的最长路 int main()
{cin >> n >> m;s = 1;for(int i=1;i<=m;i++){int u,v,w; cin >> u >> v >> w;edge[u].push_back({v,w}); in[v]++;}//拓扑排序queue<int> q;//先把除1外所有入度为0的结点加入队列 for(int i=2;i<=n;i++){if(in[i] == 0) q.push(i);f[i] = -1e9;}while(q.size()){int u = q.front(); q.pop();for(auto& t:edge[u]){int v = t.first;in[v]--;if(in[v] == 0) q.push(v);}}q.push(1);while(q.size()){int u = q.front(); q.pop();for(auto& t:edge[u]){int v = t.first, w = t.second;in[v]--;f[v] = max(f[v], f[u] + w);if(in[v] == 0) q.push(v);}}if(f[n] == -1e9) cout << -1 << endl;else cout << f[n] << endl;return 0;
}
http://www.dtcms.com/a/351872.html

相关文章:

  • 广度优先遍历-BFS
  • 【跨国数仓迁移最佳实践7】基于MaxCompute多租的大数据平台架构
  • springboot实现合同生成
  • Odoo 企业版用户手册[新版] 前言 00.3-企业版功能模块全景图
  • C语言 指针
  • 消防设施安全员证核心考点:消防设施操作与维护高频知识点汇总
  • 聊聊测试覆盖率与测试质量之间的关系
  • 使用powerquery处理数据,取时间或者日期之前的
  • conda环境--相关记录
  • THM TryHack3M Subscribe WP
  • 科技信息差(8.26)
  • 亚马逊云科技免费套餐新政解析与实战:数据分析与可视化平台
  • Slice-100K:推动AI驱动的CAD与3D打印创新的多模态数据集
  • Mysql 判断查询条件索引是否生效步骤,使用说明,示例演示
  • 集成电路学习:什么是ResNet深度残差网络
  • Redis高级篇:在Nginx、Redis、Tomcat(JVM)各环节添加缓存以实现多级缓存
  • Docker-Docker思想
  • 软考-系统架构设计师 计算机系统基础知识详细讲解
  • 今日科技热点 | AI加速变革,量子计算商用化,5G应用新机遇
  • IDEA插件推荐
  • 【prism】Prism 弹窗在 ViewModel 中控制大小的实践总结
  • 工业自动化系统架构-(规划调度执行与协调)
  • 《Java反射与动态代理详解:从原理到实践》
  • 如何让Windows桌面井井有条?
  • 模型解释性:使用 SHAPASH 在贷款被拒原因的解释性(三)
  • Java大厂面试实战:从Spring Boot到微服务架构的深度剖析
  • 【公告】模式更改
  • 县域创新升级:直面瓶颈,重塑成果转化路径
  • 缺少fuser导致oracle自动补丁失败
  • 【第三章】软件测试缺陷管理:从判断到回归的全流程实践指南​