51nod1459(带权值的dijkstra)

时间:2022-04-14 05:28:48

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1459

题意:中文题诶~

思路:带权值的最短路,这道题数据也没啥特殊,spaf,floyd, dijkstra 都可以过,我这里就写个dijkstra好了...

dijkstra算法和最小生成树的prime有点像,prime算法是将所有点分成两个点集s, w,初始时s中只有一个点,然后依次将w中距离s集合最近的点加入s集合中,直至w为空集..

这两个算法的区别是dijkstra还要依次以点集s为中间点来更新点集w中的点到出发点的最小距离,最终自然能得到出发点到终止点的最小距离啦..

dijkstra模板中更新出发点到w点集的距离时不需要考虑距离相同的情况,而本题则需要更新为权值更大的点即可...

 #include <bits/stdc++.h>
#define INF 1000000000
#define MAXN 1000
using namespace std; int mp[MAXN][MAXN], low[MAXN], tag[MAXN], n, m, rank[MAXN], vis[MAXN];
// low[j]记录出发点到点j的最短距离,tag[j]标记点j是否被选中过, vis[j]记录出发点到点j的最大权值 void dijkstra(int s, int e){
for(int i=; i<n; i++){ //初始化
low[i]=mp[s][i];
}
vis[s]=rank[s];
low[s]=;
for(int i=; i<n; i++){
int MIN=INF;
for(int j=; j<n; j++){
if(low[j]<MIN&&!tag[j]){
MIN=low[j];
s=j;  //s为当前选中的点
}
}
tag[s]=;
for(int j=; j<n; j++){ //更新各点到出发点的最小距离
if(low[j]>mp[s][j]+low[s]){
low[j]=mp[s][j]+low[s];
vis[j]=vis[s]+rank[j];
}else if(low[j]==mp[s][j]+low[s]){ //若距离相等则更新权值更大的点
vis[j]=max(vis[s]+rank[j], vis[j]);
}
}
}
cout << low[e] << " " << vis[e] << endl;
} int main(void){
int s, e;
cin >> n >> m >> s >> e;
for(int i=; i<n; i++){
cin >> rank[i];
}
for(int i=; i<n; i++){
for(int j=; j<n; j++){
mp[i][j]=mp[j][i]=INF;
}
}
while(m--){
int x, y, z;
cin >> x >> y >> z;
mp[x][y]=mp[y][x]=z;
}
dijkstra(s, e);
return ;
}