总结bellman_ford算法:
主要考虑到带负权边的图,这样的图,对于存在负权边时无法用dfs,prim等求最短路的。因为每次更新不能确定是否有正值与负值相加得出错误的最短路径的点。
bellman_ford就可以解决这个问题。
判断方法:
若图不存在负权值的时候,每一次做全部边的松弛操作(判断src->j的长度是否大于src-->i+i-->j的长度)则可至少确定一个点的最短路径。则n-1次后就可确定所有点的最短路径。否则则知道存在负权边。
因此该算法是做n次所有边的松弛操作。设m条边,复杂度0(n*m);
该算法效率不高,适合稠密图。同时该算法一般可以用spfa算法代替。
后面再做一道spfa算法的题。
#include<iostream>
#include<cstdio>
using namespace std;
int num=0;
struct edge{
int u,v;
double c,r;
}edges[1000];
double dis[110];
bool bellman_ford(int s,double value)
{
int i;
bool flag;
for(i=0;i<110;i++)
{
dis[i]=0;
}
dis[s]=value;
while(dis[s]<=value)
{
flag=false;
for(i=0;i<num;i++)
{
if(dis[edges[i].v]<(dis[edges[i].u]-edges[i].c)*edges[i].r)
{
dis[edges[i].v]=(dis[edges[i].u]-edges[i].c)*edges[i].r;
flag=true;
}
}
if(!flag)
return dis[s]>value;
}
return true;
}
int main()
{
int i,n,m,s,a,b;
double ab1,ab2,ba1,ba2;
double value;
cin>>n>>m>>s;
scanf("%lf",&value);
for(i=0;i<m;i++)
{
scanf("%d%d%lf%lf%lf%lf",&a,&b,&ab1,&ab2,&ba1,&ba2);
edges[num].u=a;
edges[num].v=b;
edges[num].r=ab1;
edges[num].c=ab2;
num++;
edges[num].u=b;
edges[num].v=a;
edges[num].r=ba1;
edges[num].c=ba2;
num++;
}
if(bellman_ford(s,value))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}