0
点赞
收藏
分享

微信扫一扫

PTA: 天梯地图 [狄杰斯特拉+堆优化+链式前向星]

一只1994 2022-04-01 阅读 47

题目

输入样例1:

10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
5 4 0 2 3
5 9 1 1 4
0 6 0 1 1
7 3 1 1 2
8 3 1 1 2
2 5 0 2 2
2 1 1 1 1
1 5 0 1 3
1 4 0 1 1
9 7 1 1 3
3 1 0 2 5
6 3 1 2 1
5 3

输出样例1:

Time = 6: 5 => 4 => 8 => 3
Distance = 3: 5 => 1 => 3

输入样例2:

7 9
0 4 1 1 1
1 6 1 3 1
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 3 1
3 2 1 2 1
4 5 0 2 2
6 5 1 2 1
3 5

输出样例2:

Time = 3; Distance = 4: 3 => 2 => 5

思路

两种路径,两次狄杰斯特拉就可以了。

代码

#include <cstdio>
#include <queue>
#include <map>
#include <cstring>
#include <set>
#include <stack>

using namespace std;

typedef pair<int, int> PII;
const int maxn = 505;
struct Edge{
    int to, l, t, next;
}edge[maxn*maxn];
int tot = -1;
int head[maxn*maxn];
void add(int u, int v, int l, int t) {
    ++tot;
    edge[tot].to = v;
    edge[tot].l = l;
    edge[tot].t = t;
    edge[tot].next = head[u];
    head[u] = tot;
}
int dist[maxn], tme[maxn];
int pathd[maxn], patht[maxn];
int cnt[maxn], lenth[maxn];
bool operator<(const PII& a, const PII& b) {
    return a.second > b.second;
}
int s, d;
priority_queue<PII> que;

void dij1() {
    memset(dist, 0x3f, sizeof(dist));
    memset(cnt, 0, sizeof(cnt));
    set<int> vis;
    dist[s] = 0;
    cnt[s] = 1;
    que.push({s, 0});
    while(que.size()) {
        auto tmp = que.top(); que.pop();
        if(vis.count(tmp.first)) continue;
        vis.insert(tmp.first);
        for(int i = head[tmp.first]; i != -1; i = edge[i].next) {
            int tl = edge[i].l + dist[tmp.first];
            if(tl < dist[edge[i].to]) {
                dist[edge[i].to] = tl;
                pathd[edge[i].to] = tmp.first;
                cnt[edge[i].to] = cnt[tmp.first]+1;
                que.push({edge[i].to, tl});
            }
            else if(tl == dist[edge[i].to] && cnt[edge[i].to]>cnt[tmp.first]+1) {
                cnt[edge[i].to] = cnt[tmp.first]+1;
                pathd[edge[i].to] = tmp.first;
                que.push({edge[i].to, tl});
            }
        }
    }
}
void dij2() {
    memset(tme, 0x3f, sizeof(tme));
    memset(lenth, 0x3f, sizeof(lenth));
    set<int> vis;
    tme[s] = 0;
    lenth[s] = 0;
    que.push({s, 0});
    while(que.size()) {
        auto tmp = que.top(); que.pop();
        if(vis.count(tmp.first)) continue;
        vis.insert(tmp.first);
        for(int i = head[tmp.first]; i != -1; i = edge[i].next) {
            int tl = edge[i].t + tme[tmp.first];
            if(tl < tme[edge[i].to]) {
                tme[edge[i].to] = tl;
                patht[edge[i].to] = tmp.first;
                lenth[edge[i].to] = lenth[tmp.first]+edge[i].l;
                que.push({edge[i].to, tl});
            }
            else if(tl == tme[edge[i].to] && lenth[edge[i].to]>lenth[tmp.first]+edge[i].l) {
                lenth[edge[i].to]=lenth[tmp.first]+edge[i].l;
                patht[edge[i].to] = tmp.first;
                que.push({edge[i].to, tl});
            }
        }
    }
}

int main(void)
{
  //  freopen("in.txt", "r", stdin);
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; ++i) {
        head[i] = pathd[i] = patht[i] = -1;
    }
    int u, v, o, l, t;
    while(m--) {
        scanf("%d%d%d%d%d", &u, &v, &o, &l, &t);
        add(u, v, l, t);
        if(!o)
            add(v, u, l, t);
    }
    scanf("%d%d", &s, &d);
    stack<int> ansDis, ansTim;
    dij1(); dij2();
    ansDis.push(d);
    int i = pathd[d];
    while(i != -1) {
        ansDis.push(i);
        i = pathd[i];
    }
    ansTim.push(d);
    i = patht[d];
    while(i != -1) {
        ansTim.push(i);
        i = patht[i];
    }
    if(ansDis == ansTim) {
        printf("Time = %d; Distance = %d:", tme[d], dist[d]);
        printf(" %d", ansDis.top()); ansDis.pop();
        while(ansDis.size()) {
            printf(" => %d", ansDis.top()); ansDis.pop();
        }
    }
    else {
        printf("Time = %d:", tme[d]);
        printf(" %d", ansTim.top()); ansTim.pop();
        while(ansTim.size()) {
            printf(" => %d", ansTim.top()); ansTim.pop();
        }
        printf("\nDistance = %d:", dist[d]);
        printf(" %d", ansDis.top()); ansDis.pop();
        while(ansDis.size()) {
            printf(" => %d", ansDis.top()); ansDis.pop();
        }
    }
    return 0;
}
举报

相关推荐

0 条评论