最短路径学习总结

问题描述:给定图,求两点间的最短距离。
主要有三种算法:
1.floyd算法:枚举任意点作为中间点动态更新剩余点间的距离。优点:可以求出所给图中任意两点间的最小距离;缺点:时间复杂度高,点如果有达到三位数或者更多则不适用。适用于点较少的图。
主要步骤:1.确定所给图是有向图还是无向图;
2.初始化所有点的距离无穷,将所给的图存到邻接矩阵之中;
3.从第一个点开始枚举,对剩余的所有的以枚举点为中间点的两点的距离进行动态更新,小了更新,大了不更新;
4.直到枚举完所有点,算法结束邻接矩阵中存的就是任意两点间的最近距离了。


代码如下:

void floyd(int n)//n为节点数 
{
    for(int k=1;k<=n;++k)//枚举中间点 
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)//扫描整个矩阵 又向图与无向图都适用 
            {                    
                if(map[i][j]>map[i][k]+map[k][j])
                {
                   map[i][j]=map[i][k]+map[k][j];
                }
            }
         } 
    }
}

2.dijkstra算法:将所有点分成两个集合,每次确定一点,直到加入所有点。优点:可以快速确定所给两点间的最短距离与路线,较flyod有较大提升;缺点:一次只能求出两个点间的最短距离。
具体步骤:1.初始化矩阵,将题中所给图存到邻接矩阵之中;
2.确定所求起点与终点;
3。将起点加入集合S(确定点集),剩余点为集合U,以起点为原点更新与之邻接且没有加入集合S的点到起点str的距离(注意:此处是dijkstra与prim的唯一区别):
4.在U集合中选取与起点str最近的点;
5.加入集合S;
6.以此点为原点更新与之邻接且在集合U中的点到起点str的距离,小了更新。
7.依此,直到所有点加入集合S为止。


代码如下:

void dijkstra(int n,int s)//n为总结点数  s为起点 
{
    memeset(vis,false,sizeof(vis));//初始化标记数组  
    for(int i=1;i<=n;++i)  dis[i]=map[s][i];//初始化到起点的最近距离 
    dis[s]=0;// 
    for(int i=1;i<=n;++i)
    {
        int top=inf,k=s;//记录最短路和这个点 k必须初始化
        for(int j=1;j<=n;++j)//找出最短距离 
        {
            if(!vis[j]&&dis[j]//如果剩下的点都是零点 那么此条件不可能成立 即k伪随机值
            {
                top=dis[j]; k=j;
             } 
        }
     //   if(top==inf)  break;防止k为随机值 如果只剩下零点就不用更新了 可以优化时间复杂度
        vis[k]=true;//将k加入集合 
        for(int i=1;i<=n;++i)//更新 
        {
            if(!vis[i]&&dis[j]>dis[k]+map[k][j])
            {
                dis[j]=dis[k]+map[k][j];
            }
        }
     } 
 } 

注意事项:1.题中如果没有直接给出边的信息,你应该将他适当转化,使其能存入到邻接矩阵中;
2.存图时,应该考虑是否有多重边,根据题意,筛选出两点间的最小边或最大边;
3.求最短路径最直接的问题就是图中的总节点数目,题中可能没有给确定的数目,这时就应该用暴力解决,枚举满足题意得所有点;
4.有些情况下要考率是否起点和终点相同,可能会在这挖坑;

你可能感兴趣的:(14-最短路径,暑假集训)