Bellman-Ford 求最长路

洛谷 - P1807
题目传送
题意:
在这里插入图片描述
在这里插入图片描述

思路:
只有DAG(有向无环图)才有最长路

最长路其实思想和最短路的思想是一样的,如果没有负权值,那么我们完全可以用dijkstar解决(在枚举当前最短路径的时候,直接枚举最长路径即可)。

但是很不幸,这个题有负权值,那么dij解决不了,如果用floyd的话,看到数据为 1 <= n <= 1500,看到会t掉。所以这里用另外一种方法解决,他就是 Bellman-Ford (时间复杂度为(n*m),也就是点的数量乘边的数量,求单源路径)

算法原理:
才刚刚学,不可能理解得那么透彻,也是通过n-1次枚举中间点来更新现在的最大值,但是对于每个循环每条路的中间点都是不一定相同的(就听我乱扯叭)

行了。。。越说越离谱。。。我只是这样好记点

别人的详解算法

AC代码

#include <bits/stdc++.h>
inline long long read(){char c = getchar();long long x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 1e5 + 10;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const double EEE = exp(1);
const int mod = 1e9+7;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
int uv[N][2],dis[2000],val[N];
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    int n,m;
    cin >> n >> m;
    fill(dis,dis+2000,-INF);//因为是求最长路,所以赋值为-INF
    dis[1] = 0;
    for(int i = 1;i <= m;i++)
    {
        int a,b,c;
        cin >> a >> b >> c;
        uv[i][0] = a,uv[i][1] = b,val[i] = c;//记录哪个点到哪个的权值
    }
    for(int i = 1;i <= n-1;i++)
        for(int j = 1;j <= m;j++)
            dis[uv[j][1]] = max(dis[uv[j][1]],val[j]+dis[uv[j][0]]);
            //这里就是核心了,通过n-1次枚举中间点来更新
    if(dis[n] != -INF) cout << dis[n] << endl;
    else cout << -1 << endl;//1到n不连通
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于解最短径的算法,而不是最长。如果要最长,需要使用其他算法,如Acyclic Longest Path算法或Bellman-Ford算法。这里以Acyclic Longest Path算法为例进行介绍。 Acyclic Longest Path算法是一种用于有向无环图(DAG)中最长的动态规划算法。它的基本思想是对DAG的所有节点进行拓扑排序,并按照拓扑序列的顺序依次计算每个节点的最长。具体地,假设有一个有向无环图DAG=(V,E),其中V表示节点集合,E表示边集合。对DAG进行拓扑排序,得到节点的拓扑序列。对于拓扑序列中的每个节点v,计算其前驱节点的最长,然后将最长加上v到其前驱节点的边权值,得到v的最长。重复上述过程直到计算完所有节点的最长。 下面是一个使用Acyclic Longest Path算法解DAG中最长的C++代码实现: ```c++ #include <iostream> #include <vector> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; int main() { int n, m; cin >> n >> m; vector<vector<pair<int, int>>> graph(n); // 邻接表表示图 vector<int> in_degree(n, 0); // 记录每个节点的入度 vector<int> dist(n, -INF); // 记录每个节点的最长 for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; graph[u].push_back({v, w}); // 添加边 in_degree[v]++; // 统计入度 } queue<int> q; // 拓扑排序所需队列 // 将入度为0的节点加入队列 for (int i = 0; i < n; i++) { if (in_degree[i] == 0) { q.push(i); dist[i] = 0; // 初始距离为0 } } while (!q.empty()) { int u = q.front(); q.pop(); for (auto p : graph[u]) { int v = p.first, w = p.second; dist[v] = max(dist[v], dist[u] + w); // 更新最长 if (--in_degree[v] == 0) q.push(v); // 将入度为0的节点加入队列 } } for (int i = 0; i < n; i++) { cout << "Node " << i << " longest path: " << dist[i] << endl; } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值