今天的训练成功由题目把四种求最短路径的方法都复习了一遍,也算是路遇难题,各显神通吧。
下面总结一下其中的三种算法(spfa算法是第三种算法的优化,所以只总结第1,2,4这三种算法):
对于Floyed算法:
算法的形式就比较暴力,三重循环过滤中间点对每个a[i][j]的缩短作用,过滤完之后结果就是最短路径,而且可以处理负权,易错点就是第一重循环的作用一定要注意。
算法的代码如下:
for (k=1;k<=n;k++){//第一重循环为中间点
for (i=1;i<=n;i++){
for (j=1;j<=n;j++){
if (a[i][j]>a[i][k]+a[k][j]){
a[i][j]=a[i][k]+a[k][j];
}
}
}
}
对于Dijkstra算法:
算法可处理单源头的最短路径问题,简而言之就是找点更新,每次找与源头点的最近的未访问过的点,用这个点的距离去更新余下未访问的点,重复n-1次,得到的dis数组之中存的便是源头到该点的最短距离。
算法的代码如下:
int Dijkstra(){
int i,j,k,l;
int xx;
value=1061109567;
memset (dis,0x3f,sizeof(dis));
memset (visit,0,sizeof(visit));
dis[1]=0;
for (i=1;i<=n-1;i++){
xx=1061109567;
place=0;
for (j=1;j<=n;j++){
if (!visit[j]&&dis[j]<xx&&dw1[j]){
place=j;
xx=dis[j];
}
}
if (place){
visit[place]=1;
for (j=1;j<=n;j++){
if (!visit[j]&&dis[j]>dis[place]+a[place][j]&&dw1[j]){
dis[j]=dis[place]+a[place][j];
}
}
}
}
for (i=1;i<=n;i++) {value=min(value,dis[i]+p[i]);}
return value;
}
而对于spfa算法:
算法也是可以处理单源头问题,算法的思路就是反复更新,每次找到路径缩小的点入队,然后用他更新余下他能到达的点,也是在dis数组中存放距离,也可以用于判断是否出现负权回路。
算法代码如下:
void spfa(){
int i,j,k,l;
int u,v;
queue<int>qq;
qq.push(1);
s[1]=0;
visit[1]=1;
total[1]++;
while (!qq.empty()){
u=qq.front();
qq.pop();
visit[u]=0;
for (i=head[u];i!=-1;i=p[i].pre){
v=p[i].to;
if (s[v]>p[i].val+s[u]){
s[v]=p[i].val+s[u];
if (!visit[v]){
qq.push(v);
visit[v]=1;
total[v]++;
if (total[v]>=n){
cout<<"YES"<<endl;
return ;
}
}
}
}
}
cout<<"NO"<<endl;
}
知识点差不多已经通了一遍,明天的训练以刷体和看博客为主。