51 NOD 1459 迷宫问题 解题报告 (优先队列 dijkstra)

传送门:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1459

这题题意很明显是最短路的裸题,迪杰斯特拉或者是Bellm—Ford算法都可以,虽然是模板题,但是还是要自己独立实现一下,模板可以算是算法实现的基础吧,有时候其实自己觉得模板都理解了,但是自己实现的时候就会遇到很多细小的困难。最好还是不看答案独立实现一遍。

这题和普通的模板有一点差别就是在最短路选择上,如果最短路唯一那没啥好说的,但是如果最短路有不同的选择,那么这时候就要选择得分比较大的那一条路,也算是贪心了。

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int MAXN = 500000;
struct node{
    int v, w, next;
}edge[MAXN];
int head[MAXN], cnt = 0, score[MAXN], dis[MAXN], s[MAXN], vis[MAXN];
void add(int u, int v, int w){
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
struct point{
    int x, d;
    point(){};
    point(int x, int d):x(x),d(d){};
    friend bool operator < (point x1, point x2){  //运算符重载
        return x1.d > x2.d;
    }
};
int dijkstra(int st, int ed, int n){
    memset(dis, 0x3f, sizeof(dis));  //int 四个字节,每个字节设为3f
    memset(vis, 0, sizeof(vis)); //vis数组是dijkstra算法的精髓之一,可以把运算速度提高三分之一
    dis[st] = 0;
    s[st] = score[st];
    priority_queue qu;
    qu.push(point(st, 0));
    while(!qu.empty()){
        int u = qu.top().x;
        qu.pop();
        if(vis[u] == 0){ // dijkstra算法可以处理非负环图的原理就在这里
            vis[u] = 1;
            for(int i = head[u];i != -1;i = edge[i].next){
                int v = edge[i].v;
                if(!vis[v] && dis[v] > dis[u] + edge[i].w){ // 有向无环图的三角定理
                    dis[v] = dis[u] + edge[i].w;
                    s[v] = s[u] + score[v];
                    qu.push(point(v, dis[v]) );  //如果V节点的边没有松弛过,那么加入优先队列
                }
                else if(!vis[v] && dis[v] == dis[u] + edge[i].w){  
                    dis[v] = dis[u] + edge[i].w;
                    s[v] = max(s[v], s[u] + score[v]);
                    qu.push(point(v, dis[v]) );
                }
            }
        }
    }
    return dis[ed];
}
int main()
{
    //freopen("input.txt", "r", stdin);

    memset(s, -1, sizeof(s));
    int n, m, st, ed;
    scanf("%d %d %d %d", &n, &m, &st, &ed);
    for(int i = 0;i < n;++i){
        head[i] = -1;
        scanf("%d", &score[i]);
    }

    for(int i = 0;i < m;++i){
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        add(u, v, w);
        add(v, u, w);
    }
    /*for(int i = 0;i < n;++i){
        printf("%d", i);
        for(int j = head[i];j != -1;j = edge[j].next)
            printf("     %d",edge[j].v);
        printf("\n");
    }*/   //这里是测试邻接表是否读入成功的代码
    int d = dijkstra(st, ed, n);
    int ans = s[ed];
    printf("%d %d\n", d, ans);
    return 0;
}

 

你可能感兴趣的:(51 NOD 1459 迷宫问题 解题报告 (优先队列 dijkstra))