迪杰斯特拉算法为啥不能有负权边
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迪杰斯特拉算法为啥不能有负权边相关的知识,希望对你有一定的参考价值。
参考技术A 你是否弄错了,是单源最短路径的Dijkstra算法不能边权为负值,因为其算法为从当前最小路径长度开始,逐步增加,并且不再回头运算,如果有边权为负值,自然用bellman算法还有一个可以选择的是Floyd算法,这后面两者的使用前提都是不存在负权回路,原因是一圈转下来变小了,再转一圈就更小了
而Kruskal算法是求最小生成树的,边权为负值什么问题都没有本回答被提问者采纳
求多重邻接表的迪杰斯特拉算法
无向图的多重邻接表不是邻接矩阵!!
#define MAX_VERTEX_NUM 20 //最大顶点个数#define MAX_NAME 10 //顶点信息的最大长度
#define MAX_INFO 80 //信息最大长度
#define TRUE 1
#define FALSE 0
typedef int VRType; //顶点类型
typedef char InfoType;
typedef char VertexType[MAX_VERTEX_NUM];
typedef enumDG,DN,UDG,UDNGraphKind; //有向图,有向网,无向图,无向网
typedef struct ArcCell
VRType adj;//顶点关系类型,对无权图用1或0
//表示相邻否;对带权图,为权值类型
InfoType *info;//该弧相关信息指针
ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
VertexType vex[MAX_VERTEX_NUM]; //顶点向量
AdjMatrix arcs; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数,弧数
GraphKind kind; //图种类标志
MGraph;
int LocateVex(MGraph G,VertexType v1)
int i;
for(i=0;i<G.vexnum;++i)
if(!strcmp(G.vex[i],v1)) //找到该返回当前位置
return i;
return -1;
void CreateDN(MGraph *G)
/* 采用数组(邻接矩阵)表示法,构造有向网G */
int i,j,k,w,IncInfo;
char s[MAX_INFO],*info;
VertexType va,vb;
printf("请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0): ");
scanf("%d,%d,%d",&(*G).vexnum,&(*G).arcnum,&IncInfo);
printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME);
for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */
fflush(stdin);
scanf("%s",(*G).vex[i]);
for(i=0;i<(*G).vexnum;++i) /* 初始化邻接矩阵 */
for(j=0;j<(*G).vexnum;++j)
(*G).arcs[i][j].adj=0; /* 网 */
(*G).arcs[i][j].info=NULL;
printf("请输入%d条弧的弧尾 弧头 权值(以空格作为间隔): \n",(*G).arcnum);
for(k=0;k<(*G).arcnum;++k)
scanf("%s%s%d",va,vb,&w); /* %*c吃掉回车符 */
i=LocateVex(*G,va);
j=LocateVex(*G,vb);
(*G).arcs[i][j].adj=w; /* 有向网 */
if(IncInfo)
printf("请输入该弧的相关信息(<%d个字符): ",MAX_INFO);
gets(s);
w=strlen(s);
if(w)
info=(char*)malloc((w+1)*sizeof(char));
strcpy(info,s);
(*G).arcs[i][j].info=info; /* 有向 */
(*G).kind=DN;
void ShortestPath_DIJ(MGraph G,int v0)
//迪杰斯特拉算法
//用Dijkstra算法求有向网G的V0顶点到其余顶点V的最短路径P[v]及其带权长度D[v]
int i,v,w,min;
int D[MAX_VERTEX_NUM]; //装载路径长度,即值
int final[MAX_VERTEX_NUM];//final[v]为TRUE即求得V0到V的最短路径
char *p[MAX_VERTEX_NUM]; //记录最短路径
for(v=0;v<G.vexnum;++v)
final[v] = FALSE;
D[v] = 0; //每个路径清0
p[v] = (char*)malloc(10*sizeof(char));//初始化路径
strcpy(p[v],G.vex[v0]); //路径上先取得V0的值
final[v0] = TRUE;
for(w=0;w<G.vexnum;++w)//先将V0第一个邻接顶点处理
if(G.arcs[v0][w].adj!=0 && !final[w])//当权值不为0和路径未找出
D[w] += G.arcs[v0][w].adj; //该点路径长度记录下来
strcat(p[w],G.vex[w]); //该点记录在路径上
for(i=1;i<G.vexnum;++i) //处理其余G.vexnum-1个顶点
min = 999;
for(w=0;w<G.vexnum;++w)
if(D[w]<min && D[w]!=0 && !final[w]) //在已有路径长度中找最短路径
min = D[w]; v = w; //记下最短路径和其下标(其下标相当于哪个顶点)
final[v] = TRUE; //离V0最近的V完成记录
for(w=0;w<G.vexnum;++w) //更新当前最短路径和距离
if(D[w]==0 && !final[w] && G.arcs[v][w].adj!=0) //在V上找路径
D[w] = min+G.arcs[v][w].adj; //修改路径距离
strcpy(p[w],p[v]); //这种情况的先将V上的路径复制到W上
strcat(p[w],G.vex[w]);
else if((!final[w] && min+G.arcs[v][w].adj<D[w]) && G.arcs[v][w].adj!=0)
D[w] = min + G.arcs[v][w].adj;
strcpy(p[w],p[v]); //这种情况的先将V上的路径复制到W上
strcat(p[w],G.vex[w]);//再把W上的路径连上
//for(i=0...
for(i=0;i<G.vexnum;++i)
printf("最短路径=%s,路径长度=%d\n",p[i],D[i]);
free(p[i]);
void DestroyGraph(MGraph *G)
int i,j;
for(i=0;i<G->vexnum;++i)
for(j=0;j<G->vexnum;++j)
if(G->arcs[i][j].info)
free(G->arcs[i][j].info);
G->arcs[i][j].info = NULL;
G->arcnum = G->vexnum = 0;
int main(void)
MGraph G;
int i,j;
CreateDN(&G);
//for(i=0;i<G.vexnum;++i) printf("%s ",G.vex[i]);
for(i=0;i<G.vexnum;++i)
for(j=0;j<G.vexnum;++j)
printf("%5d ",G.arcs[i][j].adj);
printf("\n");
ShortestPath_DIJ(G,0);
return 0;
/*
请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0): 6,8,0
请输入6个顶点的值(<10个字符):
v0
v1
v2
v3
v4
v5
请输入8条弧的弧尾 弧头 权值(以空格作为间隔):
v0 v2 10
v0 v4 30
v0 v5 100
v1 v2 5
v2 v3 50
v3 v5 10
v4 v3 20
v4 v5 60
0 0 10 0 30 100
0 0 5 0 0 0
0 0 0 50 0 0
0 0 0 0 0 10
0 0 0 20 0 60
0 0 0 0 0 0
*/
写得不全的一个小程序,不知是否你要的。 参考技术A include<iostream>
#include<cmath>
using namespace std;
const int maxint=0xfffffff;
struct xyz
a[101];
int s,t,f[101]=,n,m;
double map[101][101]=,ds[101];
double cal(int x,int y)
void init()
int i,x,y;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
scanf("%d",&m);
for(i=1;i<=m;i++)
scanf("%d%d",&s,&t);
void dijsktra()
int i,j,minn,k;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(map[i][j]==0)map[i][j]=maxint;
for(i=1;i<=n;i++)ds[i]=map[s][i];
for(i=1;i<=n;i++)
minn=maxint;
k=0;
for(j=1;j<=n;j++)
if(!f[j]&&ds[j]<minn)
f[k]=1;
for(j=1;j<=n;j++)
if(!f[j]&&ds[k]+map[k][j]<ds[j])ds[j]=ds[k]+map[k][j];
printf("%.2lf",ds[t]);
int main()
init();
dijsktra();
return 0;
以上是关于迪杰斯特拉算法为啥不能有负权边的主要内容,如果未能解决你的问题,请参考以下文章