zoukankan      html  css  js  c++  java
  • 最短路——迪杰斯特拉算法 HDU_3790

    初识最短路,今天只弄了一个迪杰斯特拉算法,而且还没弄成熟,只会最基本的O(n^2),想弄个优先队列都发现尼玛被坑爆了,那个不应该用迪杰斯特拉算法写

    表示还是不会优化版的迪杰斯特拉算法,(使用优先队列),只会普通的O(n^2);

    用HDU_3790来详解这个算法吧。

    最短路径问题
    Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
    Submit Status

    Description

    给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
     

    Input

    输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
    (1<n<=1000, 0<m<100000, s != t)
     

    Output

    输出 一行有两个数, 最短距离及其花费。
     

    Sample Input

    3 2 1 2 5 6 2 3 4 5 1 3 0 0
     

    Sample Output

    9 11

    在迪杰斯特拉算法里,除了必要的建图和初始化,核心部分其实很简单。。。而且理解了搜索路径的过程,更加方便。

    初始化部分

    d[]数组存放当前节点到源点的最短路径,除了d[源点]=0,其余全部设置为INF

    v[i][j]数组存放从i到j的路程,在读入数据之前,全部设置为INF

    vis[]数组用来存放已经得到最短路径的点,用该数组的目的是为了防止该点被再次搜索。

    吃完饭之后忽然想到,有一点很重要没有提醒。。。在无向图里面,读入边权值时,需要v[i][j]=v[j][i]=权值,原因很简单,无向图。

    核心部分

     直接贴代码讲算了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define maxn 1<<30
    int d[1005][1005];
    int fee[1005][1005];
    int distant[1005];
    int p[1005];
    int vis[1005];
    int n,m;
    void dijst(int be,int en)//迪杰斯特拉算法的核心部分。
    {
        memset(vis,0,sizeof vis);//初始化vis数组
        int i,j,k;
        for (i=1; i<=n; i++)//初始化每个节点的最短路程和费用,在搜索前,默认都为INF
        {
            distant[i]=maxn;
            p[i]=maxn;
        }
        distant[be]=0;//源点的最短路径设置为0
        p[be]=0;
        for (i=1; i<=n; i++)//遍历所有节点
        {
            int min=maxn,minloc=0,minip=maxn;
            for (j=1; j<=n; j++)  //找出当前还没vis过的节点中的最短路径点(第一次肯定是源点)。。由于这道题涉及费用比较,所以写得长了一些。
            {
                if (vis[j]) continue;
                if (distant[j]<min)
                {
                    min=distant[j];
                    minloc=j;
                    minip=p[j];
                }
                if (distant[j]==min&&min<maxn)
                {
                    minloc= minip<=p[j]?minloc:j;
                    min=distant[minloc];
                    minip=p[minloc];
                }
            }
            vis[minloc]=1; //循环过后,minloc点必定是路径最小点,vis它一下。
            for (k=1; k<=n; k++)
            {
                if (vis[k]) continue;
                if (d[k][minloc]==maxn) continue;
                if (distant[k]>distant[minloc]+d[k][minloc]) //将上面找到的“源点”依次与所有点遍历一遍,这样基于该源点往下走的所有节点的“当前最短路”全部求出来了,当然没有路劲链接的点 长度为INF,所以不会改变,也不影响结果。
                {
                    distant[k]=distant[minloc]+d[k][minloc];
                    p[k]=p[minloc]+fee[minloc][k];
                }
                if (distant[k]==distant[minloc]+d[k][minloc])
                {
                    if (p[k]>p[minloc]+fee[minloc][k])
                        p[k]=p[minloc]+fee[minloc][k];
                }
            }
        }
    }
    
    int main()
    {
    
        while (scanf("%d %d",&n,&m)&&n)
        {
            int i,j,k;
            for (i=1; i<=n; i++)
            {
                for (j=1; j<=n; j++)//初始化距离和费用
                {
                    d[i][j]=maxn;
                    fee[i][j]=maxn;
                }
            }
            for (i=0; i<m; i++)
            {
                int a,b,c,e;
                scanf("%d %d %d %d",&a,&b,&c,&e);
                if (d[a][b]>c)  //基于这个题目,这里的判断是必须的,因为根据题意,a到b可能有好几条路,而且路程允许相等,这个时候就要比较费用大小了
                {
                    d[a][b]=d[b][a]=c;
                    fee[a][b]=fee[b][a]=e;//无向图,所以要a到b b到a都设置一下
                }
                if (d[a][b]==c&&fee[b][a]>e)
                {
                    fee[b][a]=fee[a][b]=e;
                }
            }
            int sta,end;
            scanf("%d %d",&sta,&end);
            dijst(sta,end);
            printf("%d %d
    ",distant[end],p[end]);//源点到任意点end的最短路径就保存在distant[]数组中,调用即可。
        }
        return 0;
    }
  • 相关阅读:
    适配器
    装饰器
    getOwnPropertyDescriptor
    发布订阅
    策略模式
    window.requestAnimationFrame() 和 window.cancelAnimationFrame()
    L1-056 猜数字
    L1-055 谁是赢家
    L1-054 福到了
    L1-053 电子汪
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3242199.html
Copyright © 2011-2022 走看看