你来到一个迷宫前。该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数。
还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间。游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大。现在问题来了,给定房间、道路、分数、起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么?
Input:
第一行4个整数n (<=500), m, start, end。n表示房间的个数,房间编号从0到(n - 1),m表示道路数,任意两个房间之间最多只有一条道路,start和end表示起点和终点房间的编号。第二行包含n个空格分隔的正整数(不超过600),表示进入每个房间你的得分。再接下来m行,每行3个空格分隔的整数x, y, z (0 输入保证从start到end至少有一条路径。
Output:
一行,两个空格分隔的整数,第一个表示你最少需要的时间,第二个表示你在最少时间前提下可以获得的最大得分。
Sample Input:
3 2 0 2
1 2 3
0 1 10
1 2 11
Sample Output:
21 6
思路:
最短路径,只不过多保存一个数据。
坑点:
1.注意不要形成两个0之间的死循环。
2.当路径长度相同时,如果分数更新点也要判断入队。(我在这卡了一个小时。。。。。)
代码:
SPFA版本
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 505;
int N,M,ST,EN;
struct Edge{
int to,next;
long long value;
}E[MAXN*MAXN*2];
int head[MAXN],tot;
inline void Add(int from,int to,long long value){
E[++tot].next = head[from];
E[tot].to = to;
E[tot].value = value;
head[from] = tot;
E[++tot].next = head[to];
E[tot].to = from;
E[tot].value = value;
head[to] = tot;
}
long long dis[MAXN],score[MAXN],board[MAXN];
bool vis[MAXN];
void Spfa(){
memset(vis,false,sizeof vis);
memset(dis,INF,sizeof dis);
memset(score,0,sizeof score);
vis[ST] = true;
dis[ST] = 0;
score[ST] = board[ST];
queue<int> Q;
Q.push(ST);
while(!Q.empty()){
int now = Q.front();
Q.pop();
vis[now] = false;
for(int i=head[now] ; i ; i=E[i].next){
int to = E[i].to;
if(dis[to] > dis[now] + E[i].value){
dis[to] = dis[now] + E[i].value;
score[to] = score[now] + board[to];
}
else if(dis[to] == dis[now] + E[i].value){
if(score[to] < score[now] + board[to])score[to] = score[now] + board[to];
else continue;
}
else continue;
if(!vis[to]){
vis[to] = true;
Q.push(to);
}
}
}
}
inline void init(){
memset(head,0,sizeof head);
tot = 0;
}
int main(){
while(scanf("%d %d %d %d",&N,&M,&ST,&EN) == 4){
init();
for(int i=0 ; i<N ; ++i)scanf("%lld",&board[i]);
while(M--){
int a,b;
long long c;
scanf("%d %d %lld",&a,&b,&c);
Add(a,b,c);
}
Spfa();
printf("%lld %lld\n",dis[EN],score[EN]);
}
return 0;
}
Dijkstra版本
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 505;
int dist[MAXN],score[MAXN],board[MAXN];
bool vis[MAXN];
int N,M,ST,EN;//点数N,边数M
struct Edge{
int next,to,value;
}E[MAXN*MAXN*2];
int head[MAXN],tot;
inline void Add(int from,int to,int value){
E[++tot].next = head[from];
E[tot].to = to;
E[tot].value = value;
head[from] = tot;
E[++tot].next = head[to];
E[tot].to = from;
E[tot].value = value;
head[to] = tot;
}
struct node{
int x,len;
node(int a,int b):x(a),len(b){}
};
struct cmp{
bool operator ()(node a,node b){
if(a.len == b.len)return a.x > b.x;
else return a.len > b.len;
}
};
void Dijkstra(){
memset(dist,INF,sizeof dist);
memset(vis,false,sizeof vis);
memset(score,0,sizeof score);
dist[ST] = 0;
score[ST] = board[ST];
priority_queue<node,vector<node>,cmp> Q;
Q.push(node(ST,0));
while(!Q.empty()){
node now = Q.top();
Q.pop();
if(vis[now.x])continue;
vis[now.x] = true;
for(int i=head[now.x] ; i ; i=E[i].next){
int to = E[i].to;
if(dist[to] > dist[now.x] + E[i].value){
dist[to] = dist[now.x] + E[i].value;
score[to] = score[now.x] + board[to];
Q.push(node(to,dist[to]));
}
else if(dist[to] == dist[now.x] + E[i].value){
if(score[to] < score[now.x] + board[to]){
score[to] = score[now.x] + board[to];
Q.push(node(to,dist[to]));
}
}
}
}
}
inline void init(){
memset(head,0,sizeof head);
tot = 0;
}
int main(){
while(scanf("%d %d %d %d",&N,&M,&ST,&EN) == 4){
init();
for(int i=0 ; i<N ; ++i)scanf("%d",&board[i]);
while(M--){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
Add(a,b,c);
}
Dijkstra();
printf("%d %d\n",dist[EN],score[EN]);
}
return 0;
}