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;
    }
  • 相关阅读:
    社区检测算法--Infomap
    correlation matrices 相关矩阵
    多分类评估指标
    juniper修改用户密码
    zabbix4.4监控mysql状态
    高并发linux内核参数优化
    用脚本监控windows tcp的连接数
    使用typeperf监控系统资源
    rsync同步时报错
    windows jenkins编译报错处理
  • 原文地址:https://www.cnblogs.com/qiufeihai/p/2398455.html
Copyright © 2011-2022 走看看