在图中如果有负权边,Dijkstra就会出现错误,此时,可以使用Bellman-Ford。
我们将可以不断用所有点更新当前的dis,总共需要更新 n – 1次。
每次更新时要判断到B点与到A点再加上AB间距离的大小,以此来完成松弛操作
基础版:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
struct node
{
int x;
int y;
int d;
} num[MAXN];
int dis[MAXN];
int n, m;
void BF()
{
for(int k = 1; k < n; k++)
for(int i = 1; i <= n; i++)
if(dis[num[i].y] > dis[num[i].x] + num[i].d)
dis[num[i].y] = dis[num[i].x] + num[i].d;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &num[i].x, &num[i].y, &num[i].d);
for(int i = 1; i <= n; i++)
dis[i] = INF;
dis[1] = 0;
BF();
for(int i = 1; i <= n; i++)
printf("%d ", dis[i]);
printf("\n");
}
return 0;
}
当图中有负权环是,可以通过在松弛后通过是否还能松弛来判断。
在松弛操作时如果判断到不能再松弛了,也可以跳出来减少计算量
完全版:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
struct node
{
int x;
int y;
int d;
} num[MAXN];
int dis[MAXN];
int n, m;
bool BF()
{
bool book;
for(int k = 1; k < n; k++)
{
book = false;
for(int i = 1; i <= n; i++)
{
if(dis[num[i].y] > dis[num[i].x] + num[i].d)
{
dis[num[i].y] = dis[num[i].x] + num[i].d;
book = true;
}
}
if(book == false)
break;
}
for(int i = 1; i <= n; i++)
if(dis[num[i].y] > dis[num[i].x] + num[i].d)
return false;
return true;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i++)
scanf("%d%d%d", &num[i].x, &num[i].y, &num[i].d);
for(int i = 1; i <= n; i++)
dis[i] = INF;
dis[1] = 0;
bool flag = BF();
if(flag == false)
printf("此图含有负权回路\n");
for(int i = 1; i <= n; i++)
printf("%d ", dis[i]);
printf("\n");
}
return 0;
}