zoukankan      html  css  js  c++  java
  • HDU

    给你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
    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e4+8;
    int n, m;
    int dis[maxn][maxn], d[maxn], cost[maxn][maxn], co[maxn];
    bool sign[maxn];
    
    void dij(int s)
    {
        fill(sign, sign+maxn, 0);
        fill(d, d+n+1, inf);
        fill(co, co+n+1, inf);
        d[s] = co[s] = 0;
        for(int i = 0; i <= n; i++)//一个一个点的遍历,找出最短路径
        {
            int miao, ying = inf;
            for(int j = 0; j <= n; j++)
                if(!sign[j] && d[j] <= ying)
                    ying = d[miao = j];//把最短距离的那个点标记起来,方便后面的计算
            sign[miao] = 1;
            for(int j = 0; j <= n; j++)//在i点的基础上,一个一个点的遍历,找出由起点到重点的最短距离
            {
                if(d[j]>d[miao]+dis[miao][j])//如果(从起点到j点的距离)大于(从起点到miao点的距离)+(从miao点的距离到j点的距离)
                {
                    d[j] = d[miao]+dis[miao][j];
                    co[j] = co[miao]+cost[miao][j];
                }
                else if(d[j] == d[miao]+dis[miao][j] && co[j]>co[miao]+cost[miao][j])//如果距离相等,但(从起点到j点的花费)大于(从起点到miao点的花费)+(从miao点的距离到j点的花费)
                    co[j] = co[miao]+cost[miao][j];
            }
        }
    }
    
    int main()
    {
        int a, b, di, p;
        while(~scanf("%d%d", &n, &m) &&(n+m))
        {
            for(int i = 0; i <= n; i++)
                for(int j = 0; j <= n; j++)
                {
                    dis[i][j] = inf;
                    cost[i][j] = inf;
                }
            for(int i = 0; i<m; i++)
            {
                scanf("%d%d%d%d", &a, &b, &di, &p);
                if(dis[a][b]>di)
                {
                    dis[a][b] = di;
                    dis[b][a] = di;
                    cost[a][b] = p;
                    cost[b][a] = p;
                }
                else if(dis[a][b] == di && cost[a][b]>p)
                {
                    cost[a][b] = p;
                    cost[b][a] = p;
                }
            }
            int s, e;
            scanf("%d%d", &s, &e);
            dij(s);
            printf("%d %d
    ", d[e], co[e]);
        }
        return 0;
    }
  • 相关阅读:
    informatica 学习日记整理
    informatica 学习日记整理
    执行异步任务,并记录时间
    Calling a Web API From a .NET Client (C#)
    PIVOT运算符使用(动态行转列)
    Replication--如何使用快照来初始化化请求订阅
    Replication--备份初始化需要还原备份么?
    疑难杂症--SQL SERVER 18056的错误
    TSQL--如何突破PRINT的8000大限
    执行计划--在存储过程中使用SET对执行计划的影响
  • 原文地址:https://www.cnblogs.com/RootVount/p/10560614.html
Copyright © 2011-2022 走看看