Bellman-Ford算法及SPFA算法
Bellman-Ford算法能解决存在负权边的单源最短路径问题,还可以判断是否存在负回环
思路和dij一样
1.dis[i] 为源点s到点i的最短路径长度,初始化dis[i]=inf,dis[s] = 0;
2.枚举每一条边(v,u),若dis[u] > dis[v]+w[v][u],dis[u] = dis[v]+w[v][u];
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
const int maxn = 100;
const int inf = 0x3f3f3f3f;
int n,m,s,dis[maxn];
struct node
{
int u,v,w;
}edge[maxn*maxn];
bool Bellman_Ford(int s)
{
memset(dis,inf,sizeof dis);
dis[s] = 0;
bool flag;
for(int i = 1; i <= n; i++) //n个点
{
flag = false;
for(int j = 0; j < m; j++) //m条边
{
int x = edge[j].u;
int y = edge[j].v;
int z = edge[j].w;
if(dis[y] > dis[x]+z)
{
dis[y] = dis[x]+z;
flag = true;
}
}
if(!flag) break;
if(i==n && flag) return false;//存在负环
}
return true;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
scanf("%d%d%d",&n,&m,&s);
for(int i = 0,x,y,z; i < m; i++) //有向图
{
scanf("%d%d%d",&x,&y,&z);
edge[i].u = x,edge[i].v = y,edge[i].w = z;
}
if(Bellman_Ford(s)) printf("%d\n",dis[n]);
else printf("erro\n");
return 0;
}
例题 poj-3259
SPFA
2.SPFA算法教学
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
const int maxn = 600;
const int inf = 0x3f3f3f3f;
struct node
{
int v,w,next;
} a[maxn*maxn];
bool vis[maxn];
int dis[maxn],pre[maxn],num[maxn];
int n,m,cnt = 0;
void add(int u,int v, int w)
{
a[cnt].v = v,a[cnt].w = w,a[cnt].next = pre[u];
pre[u] = cnt++;
}
bool spfa(int s)
{
queue<int> que;
mem(vis),mem(num);
for(int i = 1; i <= n; i++)
{
dis[i] = inf;
}
dis[s] = 0;
que.push(s);
vis[s] = 1; //标记s在队列中
while(!que.empty())
{
int u = que.front();
que.pop();
vis[u] = 0;
for(int i = pre[u]; ~i; i = a[i].next)
{
int v = a[i].v;
if(dis[u]+a[i].w < dis[v])
{
dis[v] = dis[u]+a[i].w;
if(!vis[v])
{
que.push(v);
vis[v] = 1;
num[v]++;
if(num[v] >= n)
return false;
}
}
}
}
return true;
}
int main()
{
int t,w;
cin>>t;
while(t--)
{
cin>>n>>m>>w;
memset(pre,-1,sizeof(pre));
cnt = 0;
for(int i = 0,a,b,c; i < m; i++)
{
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
for(int i = 0,a,b,c; i < w; i++)
{
cin>>a>>b>>c;
add(a,b,-c);
}
if(spfa(1)) printf("NO\n"); //不存在
else printf("YES\n");
}
}