zoukankan      html  css  js  c++  java
  • HDU 3790 最短路径问题 (双重权值)

    最短路径问题

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2622    Accepted Submission(s): 825


    Problem 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
     
     
     
    刚做的时候看错题目,以为分别求最短路径和最少费用。。(两条路),然后以为2次dijkstra就OK
     
    其实题目要求的只是最短路径,而那个费用是再这条路径上的最少费用。
     
    这里要注意的是:两个点中可以有重边,特别是最短的路径的重边,应为我们求的时候只求第一个最小的的路径(以后在遇到相同的最小路径的时候就不会换值),而这条路径不能保证费用最小。
     
    所以当路径最小时,还要判断费用是不是最小,从而换值。
    还有个就是printf()的从右向左执行的问题。如果后面不加个ans,直接在printf() 里用dijkstra()的话后面那个d[end].p就会是无穷大。
     
    #include <set>
    #include <map>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cctype>
    #include <cstring>
    #include <sstream>
    #include <fstream>
    #include <cstdlib>
    #include <cassert>
    #include <iostream>
    #include <algorithm>

    using namespace std;
    //Constant Declaration
    /*
    --------------------------*/
    //#define LL long long
    #define LL __int64
    const int M=1100;//最多点数
    const int INF=1<<30;
    const double EPS = 1e-11;
    const double PI = acos(-1.0);
    /*--------------------------*/
    // some essential funtion
    /*
    ----------------------------------*/
    void Swap(int &a,int &b){ int t=a;a=b;b=t; }
    int Max(int a,int b){ return a>b?a:b; }
    int Min(int a,int b){ return a<b?a:b; }
    int Gcd(int a,int b){ while(b){b ^= a ^=b ^= a %= b;} return a; }
    /*----------------------------------*/
    //for (i = 0; i < n; i++)
    /*
    ----------------------------------*/

    struct djs
    {
    int l,p;
    }d[M],g[M][M];

    bool used[M];//标记i是否被用过
    void init(int n)
    {
    int i, j;
    for (i = 1; i <= n; i++)
    {
    for (j = 1; j <= n; j++)
    {
    g[i][j].l = INF;//初始化图没有边,默认为INF,为了一定更新
    g[i][j].p = INF;
    }
    }
    for (i = 1; i <= n; i++)
    {
    d[i].l = INF;
    d[i].p = INF;
    }

    memset(used, 0, sizeof(used));
    }



    int dijkstra(int star, int end, int n)//起点,终点,总点数(编号为1,2...n)
    {
    int min_num;//最小值的位置
    int i;
    d[star].l= 0;
    d[star].p= 0;//起点到起点的最短距离为0,很重要的一步
    for (int cnt = 0; cnt < n; cnt++)//注意别用while(n--),这样会改变n的值。n次贪心
    {
    int min = INF;
    for (i = 1; i <= n; i++)
    {
    if (!used[i] && d[i].l < min)
    {
    min = d[i].l;
    min_num = i;
    }
    }

    used[min_num] = 1;

    //把d[min_num]作为中间点,对相邻的点做松弛
    for (i = 1; i <= n; i++)
    {
    if (!used[i] && d[i].l > d[min_num].l + g[min_num][i].l)
    {
    d[i].l = d[min_num].l + g[min_num][i].l;
    d[i].p = d[min_num].p + g[min_num][i].p;
    }
    if (!used[i] && d[i].l == d[min_num].l + g[min_num][i].l && d[i].p > d[min_num].p + g[min_num][i].p)//这里的判断是关键
    {
    d[i].p = d[min_num].p + g[min_num][i].p;
    }
    }

    }
    return d[end].l;
    }





    int main()
    {
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //int t, case1 = 0;
    //scanf("%d", &t);
    int n, m;
    int i, j;
    while (scanf("%d%d", &n, &m), n + m)
    {
    init(n);
    for (i = 0; i < m; i++)
    {
    int a, b, c, c1;
    scanf("%d%d%d%d", &a, &b, &c, &c1);
    if (g[a][b].l > c)
    {
    g[b][a].l = g[a][b].l = c;
    g[b][a].p= g[a][b].p = c1;
    }//此题为无向图
    if (g[a][b].l == c && g[b][a].p > c1)//这里的判断是关键
    {
    g[b][a].p= g[a][b].p = c1;
    }

    }
    int star, end,ans;
    scanf("%d%d", &star, &end);
    ans = dijkstra(star, end, n);
    printf("%d %d\n", ans, d[end].p);
    }

    return 0;
    }
  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/qiufeihai/p/2398455.html
Copyright © 2011-2022 走看看