【概述】
从一个点出发,经过一条简单路径回到起点,称为图的环,而图的负权环就是环中所有的边的权值均为负值。
所谓负权环问题,就是判断图中是否存在一个环,里面包含的边的边权总和<0
【Bellman-Ford 算法】
Bellman-Ford 算法在计算单源最短路径时可以判断是否存在负环
关于 Bellman-Ford 算法:点击这里
int n,w,m;
int dis[N];
int k;
struct Node{
int start;
int endd;
int value;
}edge[N];
void add(int u,int v,int w){
edge[k].start=u;
edge[k].endd=v;
edge[k].value=w;
k++;
}
bool Ford(int s){
memset(dis,INF,sizeof(dis));
dis[s]=0;
for(int i=0;i<n;i++){
bool flag=true;
for(int j=0;j<k;j++){
int u=edge[j].start;
int v=edge[j].endd;
int w=edge[j].value;
if(dis[u]+w<dis[v]){
flag=false;
dis[v]=dis[u]+w;
if(i==n-1)
return true;
}
}
if(flag)
return false;
}
return false;
}
【SPFA 算法】
SPFA 算法作为 Bellman-Ford 算法的优化,其同样可以在求单源最短路的同时判断是否存在负环
关于 SPFA 算法:点击这里
struct Edge{
int from;
int to;
int dis;
Edge(int f,int t,int d):from(f),to(t),dis(d){}
};
int head[N],next[N],num;
int dis[N];
bool vis[N];
int outque[N];//进队次数
void init(){
num=0;
memset(head,-1,sizeof(head));
}
void addEdge(int from,int to,int w){
edge[num]=Edge(from,to,w);
next[num]=head[from];
head[from]=num++;
}
//计算以s为源点的最短路径
//如果图中存在s能到达的负圈,那么返回true
bool SPFA(int s){
memset(vis,false,sizeof(vis));
memset(outque,0,sizeof(outque));
memset(dis,INF,sizeof(dis));
dis[s]=0;
queue<int> Q;
Q.push(0);
while(!Q.empty()){
int x=Q.front();
Q.pop();
vis[x]=false;
outque[x]++;
if(outque[x]>n-1)
return true;
for(int i=head[x];i!=-1;i=next[i]){
Edge &e=edge[i];
if(dis[e.to]>dis[x]+e.w){
dis[e.to]=dis[x]+e.w;
if(!vis[e.to]){
vis[e.to]=true;
Q.push(e.to);
}
}
}
}
return false;
}