pat1111 Online Map

题意:输入一个图,边权包括路径长度,要消耗的时间。输出最短路径,多条则输出耗时最短的,输出耗时最多的路径,多条则输出经过点最少的。

思路:spfa跑两下就好。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <climits>

using namespace std;

const int MAX_N = 510;

struct Data {
    int to, d, t, nxt;
}e[MAX_N*MAX_N];
int head[MAX_N], cnt = 1;

void ins(int u, int v, int d, int t) {
    cnt++;
    e[cnt].to = v; e[cnt].d = d; e[cnt].t = t;
    e[cnt].nxt = head[u]; head[u] = cnt;
}

int N, M, o, d, t, u, v;

int dis[MAX_N], tim[MAX_N], from1[MAX_N], from2[MAX_N], ct[MAX_N], inq[MAX_N];
int mind, mint;

void spfa1(int r, int d) {
    for (int i = 0; i < N; i++) {
        dis[i] = tim[i] = INT_MAX;
        from1[i] = -1;
        inq[i] = 0;
    }
    dis[r] = tim[r] = 0;
    queue<int> q1;
    q1.push(r); inq[r] = 1;
    while (!q1.empty()) {
        int tp = q1.front(); q1.pop();
        for (int i = head[tp]; i; i = e[i].nxt) {
            if (dis[tp] + e[i].d < dis[e[i].to]) {
                dis[e[i].to] = dis[tp] + e[i].d;
                tim[e[i].to] = tim[tp] + e[i].t;
                from1[e[i].to] = tp;
                if (!inq[e[i].to]) {
                    inq[e[i].to] = 1;
                    q1.push(e[i].to);
                }
            } else if (dis[tp] + e[i].d == dis[e[i].to]) {
                if (tim[tp] + e[i].t < tim[e[i].to]) {
                    tim[e[i].to] = tim[tp] + e[i].t;
                    from1[e[i].to] = tp;
                    if (!inq[e[i].to]) {
                        inq[e[i].to] = 1;
                        q1.push(e[i].to);
                    }
                }
            }
        }
        inq[tp] = 0;
    }
    mind = dis[d];
}

void spfa2(int r, int d) {
    for (int i = 0; i < N; i++) {
        tim[i] = ct[i] = INT_MAX;
        from2[i] = -1;
        inq[i] = 0;
    }
    tim[r] = 0; ct[r] = 0;
    queue<int> q1;
    q1.push(r); inq[r] = 1;
    while (!q1.empty()) {
        int tp = q1.front(); q1.pop();
        for (int i = head[tp]; i; i = e[i].nxt) {
            if (tim[tp] + e[i].t < tim[e[i].to]) {
                tim[e[i].to] = tim[tp] + e[i].t;
                from2[e[i].to] = tp;
                ct[e[i].to] = ct[tp] + 1;
                if (!inq[e[i].to]) {
                    inq[e[i].to] = 1;
                    q1.push(e[i].to);
                }
            } else if (tim[tp] + e[i].t == tim[e[i].to]) {
                if (ct[tp] + 1 < ct[e[i].to]) {
                    ct[e[i].to] = ct[tp] + 1;
                    from2[e[i].to] = tp;
                    if (!inq[e[i].to]) {
                        inq[e[i].to] = 1;
                        q1.push(e[i].to);
                    }
                }
            }
        }
        inq[tp] = 0;
    }
    mint = tim[d];
}

int ro1[MAX_N], len1 = 0;
void road1(int d) {
    if (d == -1) return ;
    road1(from1[d]);
    ro1[len1++] = d;
}
int ro2[MAX_N], len2 = 0;
void road2(int d) {
    if (d == -1) return ;
    road2(from2[d]);
    ro2[len2++] = d;
}
bool isU() {
    if (len1 != len2) return false;
    for (int i = 0; i < len1; i++) {
        if (ro1[i] != ro2[i]) return false;
    }
    return true;
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    scanf("%d %d", &N, &M);
    for (int i = 0; i < M; i++) {
        scanf("%d %d %d %d %d", &u, &v, &o, &d, &t);
        if (o == 1) {
            ins(u, v, d, t);
        } else {
            ins(u, v, d, t);
            ins(v, u, d, t);
        }
    }
    scanf("%d %d", &u, &v);
    spfa1(u, v);
    spfa2(u, v);
    road1(v);
    road2(v);
    if (isU()) {
        printf("Distance = %d; ", mind);
        printf("Time = %d: ", mint);
        for (int i = 0; i < len1; i++) {
            if (i > 0) printf(" -> ");
            printf("%d", ro1[i]);
            if (i == len1-1) printf("\n");
        }
    } else {
        printf("Distance = %d: ", mind);
        for (int i = 0; i < len1; i++) {
            if (i > 0) printf(" -> ");
            printf("%d", ro1[i]);
            if (i == len1-1) printf("\n");
        }
        printf("Time = %d: ", mint);
        for (int i = 0; i < len2; i++) {
            if (i > 0) printf(" -> ");
            printf("%d", ro2[i]);
            if (i == len2-1) printf("\n");
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值