Johnson
Johnson
Johnson算法是一种Donald B. Johnson在1977年发布的:在边加权有向图中找到所有顶点对之间最短路径的算法。
jonhnson允许某些边权重为负数,但不能是负环。
通过使用Bellman-Ford 算法来计算输入图的转换,以消除所有负权重,从而允许在转换后的图上使用Dijkstra 算法。
Suurballe算法中也使用了类似的重加权技术,用于在具有非负边权重的图形中查找相同两个顶点之间最小总长度的两条不相交路径。
算法步骤
- 将新节点 添加到图中,通过零权重边连接到其他每个节点。
- 使用算法,从新的顶点 开始,为每个顶点 查找从 到 的路径的最小权重 。如果此步骤检测到负环,则终止算法使。
4 .使用计算的值重新加权原始图形的边缘:从到的边,具有长度,给出新的长度 。
3 删除 ,并使用 算法查找从每个节点 到重新加权图中其他每个顶点的最短路径。然后计算原始图中每个距离的距离,方法是将添加到算法返回的距离中。
正确性
节点 和中之间的所有路径都添加了,设为路径,它在加权后的权重由下表示
每个中的 后一项 和前一项的消去
由于重新加权增加了相同的权重,路径是原始加权图中的最短路径,当且仅当它是重新加权后的最短路径。属于从到任何节点的最短路径的边缘的权重为,因此在重新加权图中,从到每个节点的最短路径的长度变为;但是,它们仍然是最短的路径。因此,不可能有负边:如果边 在重新加权后具有负权重,则从 到 的零长度路径与此边一起将形成从 到 的负权路径,这与所有顶点与 的距离为零的事实相矛盾。负边的不存在确保了算法找到的路径的最优性。原始图中的距离可以通过加权变换,根据算法在重新加权图中计算的距离来计算。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 3e3 + 5;
int n, m, h[N], dis[N];
vector<pii> g[N];
int main() {
cin >> n >> m;
for(int w,u,v,i = 1; i <= m; i++)
{
cin >> u >> v >> w;
g[u].push_back({v, w});
}
for(int i = 1; i <= n; i++)
{
bool flag = 0;
for(int j = 1; j <= n; j++)
for(auto it : g[j])
if(h[j] + it.second < h[it.first])
flag = 1, h[it.first] = h[j] + it.second;
if(i == n && flag) return !puts("-1");
}
for(int i = 1; i <= n; i++)
{
long long ans = 0;
for(int j = 1; j <= n; j++) dis[j] = i == j ? 0 : 1e9;
priority_queue<pii, vector <pii>, greater <pii>> q;
q.push({0, i});
while(q.size())
{
auto t = q.top();q.pop();
int id = t.second;
if(t.first != dis[id]) continue;
for(auto k : g[id])
{
int it = k.first, d = t.first + h[id] - h[it] + k.second;
if(d < dis[it]) q.push({dis[it] = d, it});
}
}
for(int j = 1; j <= n; j++)
ans += 1ll * j * (dis[j] + (dis[j] < 1e9 ? h[j] - h[i] : 0));
cout << ans << endl;
}
return 0;
}
参考
初级图论
[johnson 维基百科](https://en.wikipedia.org/wiki/Johnson's_algorithm)
“风雪越是呼啸,雪莲越是绽放”
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!