传送门: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;
}