有权图的单源最短路与无权图的区别:
1.有权图的最短路不一定是经过顶点数最少的那条路
2.负值圈问题(negative-cost cycle),不考虑
收录:
1.该点(在未被收录前)已经被所有已收录上层邻接点更新
2.该点的上层邻接点已经被全部收录
因此不会有更小的dist,即该点已解决。
初始化:
dist[S]=0,dis[其他]=∞(正无穷);
path[所有]=-1;
(不能解决有负边的情况)(实际上会循环n次,外层循环改成n的计数循环也一样的)
每次收录未收录顶点中dist最小者
保证了->收录V只可能使V邻接点的路径变短=min{dist[W],dist[V]+E
} (反证法:如果收录V使非V邻接点K路径变短,
原先 dist[K]=E
+E收录后dist[K]=E
+E因为K邻接点W一定是被收录过的,且W比V先被收录;
因此E
一定小于等于E;收录V不会使非V邻接点路径变短)
BFS正好实现了无权图中每次收录顶点中dist最小者。
dist=0,1,2,3,4…
//1:新增边权
for(int j=0;j
//2:新增点权
for(int j=0;jw[j]){
w[j]=w[minid]+weight[j];
}
}
}
}
//3:求最短路径条数
for(int j=0;j
1.记录单一最短路径,单一前驱结点pre[MAXN]
2.记录所有最短路径,所有前驱结点vector
对每个结点,pre[i]是一个变长数组,存放点i的所有能产生最短路径的前驱结点
(或者设置为set
//1:找到所有最短路径
<1>pre数组不需要赋初值
<2>如果需要更新距离,dist[minid]+G[minid][i]
此时需要先清空当前pre[i]数组,然后再添加minid作为其前驱结点
由于每次找到更优的前驱时都会清空pre[i],因此pre数组不需要初始化
//1:找到所有最短路径
vector pre[MAXN];
for(int i=0;i
//2:遍历所有最短路径,找到一条使第二标尺最优的路径
- 记录最短路径的数组Path
- 临时记录当前路径的数组tempPath
- 第二标尺最优值:optValue
递归边界:到达叶子结点,即起点
将本次的临时路径tempPath的第二标尺值与最优值optValue比较
(更新optValue,使用tempPath覆盖Path)
递归式:如果当前访问结点v,遍历所有pre[v]进行递归
每次需要删除tempPath新增加的结点,
防止下一次添加结点进临时路径时,结点前面多出了一堆不属于当前路径的结点
最终Path数组中存放结果路径结点的逆序
//邻接矩阵法
#include
#define MAXN 510
#define MAXDATA 1000000000
using namespace std;
int G[MAXN][MAXN];
int nv,ne,c1,c2;
int dis[MAXN];
int collected[MAXN];
void Dijkstra1(){
fill(dis,dis+nv,MAXDATA);
dis[c1]=0;
while(1){
//1:FindMin
int minValue=MAXDATA,minId=-1;
for(int i=0;idis[minId]+G[minId][j]){
dis[j]=dis[minId]+G[minId][j];
}
}
}
}
}
int main(){
scanf("%d %d %d %d",&nv,&ne,&c1,&c2);
for(int i=0;i
//邻接表法
#include
#include
#include
#define MAXN 1010
#define INFINITY 100
using namespace std;
int Nv,Ne;
struct LNode
{
int data;
int weight;
LNode* next;
};
LNode* G[MAXN];
void CreateL(){
cin>>Nv>>Ne;
int v1,v2,w;
for(int i=0;i>v1>>v2>>w;
LNode* tmp=new LNode;
tmp->data=v2;
tmp->weight=w;
tmp->next=G[v1];
G[v1]=tmp;
}
}
int FindMin(int* dist,int* collected){
//遍历找最小:适用于稠密图
int MinDist=INFINITY;
int MinV=-1;
for(int i=0;idist[i]){
MinDist=dist[i];
MinV=i;
}
}
return MinV;
}
void Dijkstra(int S,int* dist,int* path,int* collected){
dist[S]=0;
int vetex;
while(1){
vetex=FindMin(dist,collected);
if(vetex==-1) break;
collected[vetex]=1;
LNode* w=G[vetex];
while(w){
if(collected[w->data]==-1){
if(dist[vetex]+w->weightdata]){
dist[w->data]=dist[vetex]+w->weight;
path[w->data]=vetex;
}
}
w=w->next;
}
}
}
void PrintL(int vetex,int* path){
cout<
测试数据:
7 12
0 1 2
0 3 1
1 3 3
1 4 10
2 0 4
2 5 5
3 2 2
3 4 2
3 5 8
3 6 4
4 6 6
6 5 1