最短路概念

来源:互联网 发布:文艺电影推荐知乎 编辑:程序博客网 时间:2024/06/18 07:44

刚刚一不小心被自己删了大哭大哭重写

短路习题hdu 2544  2112 1874 1596  poj 1789戳偷笑点击打开链接

大家知道最短路的算法有很多种吧,现在我来总结下:

对于无向正权图,我们可以用

dijkstar算法:不可以处理负权图,,要注意与最小生成树中的普莱姆算法中的不同之处

void dijkstar(){    //int prime()    int i,j,k,min;  //int sum=0;    for(i=0;i<n;i++)    dist[i]=mapp[0][i];    dist[0]=0,mark[0]=1;    for(i=1;i<n;i++){        min=0x3f3f3f3f,k=-1;        for(j=0;j<n;j++)        if(dist[j]<min&&mark[j]==0){            min=dist[j];            k=j;        }        mark[k]=1;        if(k==-1) break;            else{  //sum+=dist[k];        for(j=0;j<n;j++)        //在通过新加入的u点路径找到离v0点更短的路径 注:若有些邻接矩阵之前初始化为无穷大,则要判断mapp[k][j]小于无穷大       if(mark[j]==0&&mapp[k][j]+dist[k]<dist[j])            //if(mark[j]==0&&mapp[k][j]<dist[j])        dist[j]=mapp[k][j]+dist[k];                         //dist[j]=mapp[k][j];        }    }                                                              //return sum;}

floyd算法:核心代码如下

int i,j,k;for (k=0;k<n;++k) for (i=0;i<n;++i) for (j=0;j<n;++j) //实际中为防止溢出,往往需要选判断 dist[i][k]和dist[k][j]都不是Inf ,只要一个是Inf,那么就肯定不必更新if (dist[i][k]+dist[k][j]<dist[i][j]&&dist[i][k]!=INF&&dist[k][j]!=INF)  dist[i][j] = dist[i][k] + dist[k][j]; 

但是这里我们要注意循环的嵌套顺序,如果把检查所有节点K放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。

Bellman算法:

void bellman_ford(){    int i,j,dis[203];    bool flag;//用于优化的    memser(dist,MAX,dist+n);///初始化    dis[s]=0;   //源点初始化为0        m=m*2;  //此处和m = 2*m是一样的,因为建立的无向图    for(i=1;i<n;i++)//进行n-1次,n为顶点数     {         flag = false;//刚刚开始标记为假         for(j=0;j<m;j++)//对每个边         {            //if  (v.d>u.d+w(u,v))            if(dis[edge[j].u]>dis[edge[j].v]+edge[j].w){//进行松弛                 dis[edge[j].u] = dis[edge[j].v]+edge[j].w;                 flag = true;//松弛成功             }         }         if(flag!=true)  //若所有的边i的循环中没有松弛成功的             break;        ///此优化可以大大提高效率。     }     printf("%d\n",dis[t]==MAX?-1:dis[t]);//输出结果 }
SPAF算法:要用到队列

//第一步://无向图,一条无向边看为两条有向边void SPFA(int start){  queue<int>q;  int i,u;  memset(vis,0,sizeof(vis));    memset(dis,inf,sizeof(dis));  dis[start]=0;  q.push(start);    vis[start]=1;  //第二步:在队列中取点,把其vis状态设为0,对该点相邻的点(连接二者的边)进行松弛操作,修改相邻点的dis[]  //并判断相邻的点vis[]状态是否为0(不存在于队列中),如果是,将其加入到队列中  while(!q.empty())  {    u=q.front(); q.pop();    vis[u]=0;    ///松弛    for(i=1;i<=n;i++)      if(dis[u]+mapp[u][i]<dis[i])      {        dis[i]=dis[u]+mapp[u][i];        if(!vis[i])//要写在松弛成功的里面        {          q.push(i);          vis[i]=1;        }      }  }}


0 0
原创粉丝点击