• 最短路径算法


    Dijkstra算法

    时间复杂度O(N2)。

    单源最短路径算法,边权非负,基于贪心思想

    算法描述:

    设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径。

    (a)初始化:dis[v]=0x7fffffff;dis[v]=0;pre[s]=0;

    (b)for(int i=1;i<=n;i++)

       1.在未被访问过的点中找一个点u使得dis[u]是最小的。

       2.u标记为已确定最短路径。

       3.for与u相连的每个未确定最短路径的点v

          if(dis[u]+w[u][v]<dis[v]){

            dis[v]=dis[u]+w[u][v];//松弛

            pre[v]=u;//记录这条路径

          }

     

    模板题:最小花费

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 2010
    using namespace std;
    
    int n,m,x,y,a,b,peo;//n m位总人数和可转账人对数,x y z a b见题目,peo指现在的这个人
    double minn;
    double dis[maxn],z[maxn][maxn];
    bool f[maxn];
    
    void dijkstra(int d){
        for(int i=1;i<=n;i++) dis[i]=z[d][i];
        dis[d]=1;//********
        f[d]=true;//********
        for(int i=1;i<=n-1;i++){
            minn=0.0;
            for(int j=1;j<=n;j++)
                if((!f[j])&&dis[j]>minn){
                    peo=j;
                    minn=dis[j];
                }
            f[peo]=true;
            if(peo==b) break;
            for(int j=1;j<=n;j++)
                if((!f[j])&&dis[peo]*z[peo][j]>dis[j])
                    dis[j]=dis[peo]*z[peo][j];
        }
    }
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            cin>>x>>y;
            cin>>z[x][y];
            z[x][y]=(100-z[x][y])/100;//z[x][y]表示x和y转账扣完手续费后能留下的钱
            z[y][x]=z[x][y];
        }
        cin>>a>>b;
        dijkstra(a);
        printf("%.8lf
    ",100.0/dis[b]);
        return 0;
    }
    View Code

    Bellman—Ford算法

    时间复杂度O(NE),其中N是顶点数,E是边数。

    单源最短路径算法,能处理存在负边权的情况,但无法处理存在负权回路的情况,基于迭代思想

    算法描述:

    设s为起点,dis[v]为s到v的最短距离,pre[v]为v的前驱,w[j]为边j的长度,且j连接u和v。

    (a)初始化:dis[v]=0x7fffffff;dis[s]=0;pre[s]=0;

    (b)for(int i=1;i<=n-1;i++)

         for(int j=1;j<=E;j++)

           if(dis[u]+w[j]<dis[v]){

             dis[v]=dis[u]+w[j];

             pre[v]=u;

           }

    SPFA算法

    时间复杂度O(kE),其中k是一个较小的常数(所有顶点进队的频率次数),E为边数。注意,在特殊构造的图上,该算法很可能退化为O(nm)。

    单源最短路径算法,能处理存在负边权的情况,但无法处理存在负权回路的情况,是队列优化的Bellman—Ford

    算法描述:

     void spfa(){
         memset(dis,0x3f,sizeof(dis));
         memset(vis,0,sizeof(vis));
         dis[1]=0;
         vis[1]=true;
         q.push(1);
         while(q.size()){
             int x=q.front();
             q.pop();
             vis[x]=false;//取出队头
             for(int i=head[x];i;i=Next[i]){//扫描所有出边 
                 int y=ver[i],z=edge[i];
                 if(dis[y]>dis[x]+z){
                     d[y]=d[x]+z;
                     if(!vis[y]) q.push(y),vis[y]=true;
                 }
             } 
         }
     }

     

    判断有无负环:

    方法一:判断点的入队次数,若某点入队次数超过N次则存在负环。

    方法二:从起点到该点的最短路中的点数大于N。

    Floyed—Warshall算法

    时间复杂度O(N3)。

    多源最短路径算法,能处理存在负边权的情况,基于DP思想。

    算法描述:

    (a)初始化:点u和v如果有边相连,则dis[u][v]=w[u][v]。

    (b)for(int k=1;k<=n;k++)

         for(int i=1;i<=n;i++)

           for(int j=1;j<=n;j++)

             if((i!=j)&&(k!=j)&&(i!=k)&&(dis[i][k]+dis[k][j]<dis[i][j]))

               dis[i][j]=dis[i][k]+dis[k][j];

    注意:k一定要放在最外层循环!!!很重要!!!

    原理:k一次性更新了所有的点对,更新i和j时保证了i-k的距离已经被更新过了,所以f[k][i][j]表示i和j之间可通过前k个节点的最短路径。

    精髓:依次扫描每一点(k),并以该点作为中介点,计算出通过k点的其他任意两点(i,j)的最短距离。

    两种可能:1.经过第k个点不能找到最短路径,f[k][i][j]=f[k-1][i][j]

          2.经过第k个点更找到更短的路径,f[k][i][j]=f[k-1][i][k]+f[k-1][k][j]

          因为f[k]只与f[k-1]有关,所以f最外层一维空间可以省略。

    Floyed找最小环:

     for(int k=1;k<=n;k++){
         for(int i=1;i<=k-1;i++)
             for(int j=i+1;j<=k-1;j++)
                 answer=min(answer,dis[i][j]+g[i][k]+g[k][j]);//找最小环 
         for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++)
                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//找最短路径 
     }

    *参考:《信息学奥赛一本通》《算法竞赛进阶指南》。

     

  • 相关阅读:
    高级(线性)素数筛
    Dijkstra(迪杰斯特拉)算法
    简单素数筛
    【解题报告】 POJ1958 奇怪的汉诺塔(Strange Tower of Hanoi)
    4 jQuery Chatting Plugins | jQuery UI Chatbox Plugin Examples Like Facebook, Gmail
    Web User Control Collection data is not storing
    How to turn on IE9 Compatibility View programmatically in Javascript
    从Javascrip 脚本中执行.exe 文件
    HtmlEditorExtender Ajax
    GRIDVIEW模板中查找控件的方式JAVASCRIPT
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14351055.html
Copyright © 2020-2023  润新知