一. Dijkstra
1不适用于负权边。
2.求解“单源点”到其他顶点的最短路。(不适用于任两点最短路)
3.有无向图均适用。
4.其算法过程类似于最小生成树的prim算法,使用邻接矩阵时在输入之前应进行初始化,map[a][b]=0x3f3f3f3f;输入时输入的a,b距离要与map[a][b]比较,若map[a][b]>要输入的值方可对map[a][b]进行赋值。
5算法的描述
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if(i==j)
map[i][j]=0;
else
map[i][j]=0x3f3f3f3f;
}
}
int s,pos;
memset(bj,0,sizeof(bj));
for(i=1; i<=n; i++)
{
d[i]=map[1][i];
}
bj[1]=1;
for(i=0; i<n-1; i++)
{
int mi=0x3f3f3f3f;
for(j=1; j<=n; j++)
{
if(!bj[j]&&d[j]<mi )
{
mi=d[j];
pos=j;
}
}
bj[pos]=1;
for(j=1; j<=n; j++)
{
if(!bj[j] &&d[j]>map[pos][j] +d[pos])
{
d[j]=map[pos][j]+d[pos];
}
}
}
二. Bellman_ford
1.输入是使用结构体,输入的a,b,及权值和b,a及权值都要记录到结构体中。
2.可以计算边权为负值的最短路问题,适用于有向图和无向图。
3. 在边权可正可负的图中,环有零环,正环,负环3种。若判断有负环,在进行完点数减一次找最短路后,若还能松弛,则有负权边。
三. Floyd
1.输入前的初始化与Dijkstra一样,他可以求解任意两点的最短路。
2.不适用于权值为负的回路,用于无向图。
3.如果dis[i][i]!=0则证明有环。
for(k=1; k<=n; k++)
{
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if(i!=j&&(mp[i][j]>mp[i][k]+mp[k][j] ) )
{
mp[i][j]=mp[i][k]+mp[k][j];
}
}
}
PS: 原理懂了,细节还要多加注意,此能用于无向图,在
if(map[a][b]>w)
{
<span style="white-space:pre"> </span>map[a][b]=w;
<span style="white-space:pre"> </span>map[b][a]=w;//因为没有加这一条错了几次!
}
四.SPFA
1.求单源最短路,且无负环。
2.过程:
先初始化,各点距离为无穷,再将源点放入队列中,然后拿出与其相连接的点进行松弛,如果松弛成功并且队列里没有此点,将此点放入队列,并标记。直到遍历所有与当前点相连的点后,把当前点去掉标记。不断重复上面操作,直到队列中没有元素为止。
1)临接表的的实现
#include<iostream>//注意只有SPFA才有vis标记数组。
#include<queue>
#include<cstring>
using namespace std;
int n,m,z;
struct node
{
int a,w,next;//a,为各点,w为权值,next指向与当前点相连的下一个点。
}q[100010];
int head[100010],dis[100010],vis[100010];
void spfa(int s,int e)
{
int i,j,k;
queue<int >qu;
for(i=1;i<=n;i++)
dis[i]=0x3f3f3f3f;
dis[s]=0;
qu.push(s);
while(!qu.empty())
{
k=qu.front();//用刚出队的点作为源点刷新与他相连点的距离。
qu.pop();
for(i=head[k];i!=-1;i=q[i].next)
{
int a=q[i].a;
if(dis[a]>dis[ k ]+q[i].w)//如何才能刷新与其他店的距离
{
dis[a]=dis[k]+q[i].w;肯定是源点到其他点的距离大于源点+权值,故才能被更新
if(!vis[a])
{
qu.push(a);//进队,标记
vis[a]=1;
}
}
}
vis[k]=0;
}
if(dis[ n ]==0x3f3f3f3f)
cout<<"-1"<<endl;
else
cout<<dis[n]<<endl;
}
int main()
{
int i,j,k;
while(cin>>n>>m&&n&&m)
{
z=0;
int a,b,c;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(i=0;i<m;i++)
{
cin>>a>>b>>c;
q[z].a=a;
q[z].w=c;
q[z].next=head[b];//a的下一个点指向b;
head[b]=z++;
q[z].a=b;
q[z].w=c;
q[z].next=head[a];
head[a]=z++;
}
spfa(1,n);
}
return 0;
}