51nod 1459迷宫游戏 Dijkstra堆优化

51nod  1459迷宫游戏  Dijkstra堆优化

题意:给定源点和终点, 每经过一个点就会得到该点对应的分数, 每走过一条边,就会增加相应的时间,让你求源点到终点的最短时间以及在该最短时间下的最终最大得分。
分析: 依旧还是带权单源点最短路。还是用d[i].first表示从源点到i点的路径长度,用d[i].second表示从源点到i点的得分情况。
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;

//#pragma comment(linker, "/STACK:1024000000,1024000000")

#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
#define fst             first
#define snd             second

typedef __int64  LL;
//typedef long long LL;
typedef unsigned int uint;
typedef pair<int, int> PII;

const int INF = 0x3f3f3f3f;
const int MAXN = 500 + 5;
const int MAXM = 600 + 5;
int N, M, src, dest;
int x, y, z;
int A[MAXN];
struct Edge {
    int u, v, cost;
    Edge() {}
    Edge(int u, int v, int c) : u(u), v(v), cost(c) {}
};
struct QNode {
    int u, cost, sco;
    bool operator < (const QNode& e) const {
        if (cost == e.cost) {
            return sco > e.sco;
        }
        return cost < e.cost;
    }
    bool operator > (const QNode& e) const {
        return !(*this < e);
    }
} cur, rear;
vector<Edge> edges;
vector<int> G[MAXN];
PII d[MAXN];
bool vis[MAXN];
priority_queue<QNode, vector<QNode>, greater<QNode> > Q;

void init() {
    
    edges.clear();
    for (int i = 0; i < N; i ++) {
        G[i].clear();
        d[i].fst = INF;
        d[i].snd = 0;
    }
}

void addEdge(int u, int v, int dist) {
    Edge e(u, v, dist);
    edges.push_back(e);
    int m = edges.size();
    G[u].push_back(m - 1);
}

void dijkstra() {
    memset(vis, false, sizeof(vis));
    while(!Q.empty()) Q.pop();
    cur.u = src;
    cur.cost = 0;
    cur.sco = A[cur.u];
    d[cur.u].fst = 0;
    d[cur.u].snd = A[cur.u];
    Q.push(cur);
    while(!Q.empty()) {
        cur = Q.top();
        Q.pop();
        int u = cur.u;
        if(vis[u]) continue;
        vis[u] = true;
        for(uint i = 0; i < G[u].size(); i ++) {
            Edge& e = edges[G[u][i]];
            int &v = e.v;
            if(vis[v]) continue;
            if(d[v].fst > d[u].fst + e.cost || (d[v].fst == d[u].fst + e.cost && d[v].snd < d[u].snd + A[v])) {
                d[v].fst = d[u].fst + e.cost;
                d[v].snd = d[u].snd + A[v];
                rear.u = v;
                rear.cost = d[v].fst;
                rear.sco = d[v].snd;
                Q.push(rear);
            }
        }
    }
}
int main() {
#ifndef ONLINE_JUDGE
    // FIN;
#endif // ONLINE_JUDGE
    while (~scanf("%d %d %d %d", &N, &M, &src, &dest)) {
        init();
        for (int i = 0; i < N; i ++) {
            scanf("%d", &A[i]);
        }
        for (int i = 0; i < M; i ++) {
            scanf("%d %d %d", &x, &y, &z);
            addEdge(x, y, z);
            addEdge(y, x, z);
        }
        dijkstra();
        printf("%d %d\n", d[dest].fst, d[dest].snd);
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值