1003 Emergency (25 point(s))
SPFA 部分未通过 19分
思路:
1.SPFA可以在有路径长度为负的情况下,也能够实现最短路径
2.需要一个距离数组 d 对应的表示该源到图中所有点的最短距离 初始设为INF
3.需要一个是否在队列的判定数组
4.需要一个每个节点入队次数的数组,因为可能有负环,所以要做好控制,另外,因为最短路径其实是可以生成最短路径树的,最短路径树的长度最大不超过定点个树V,并且在起始的时候d[start] =0 ,就是从开始点的起始位置,实际上,距离就是0,所以已经定好了,基于这样的理论,所以每个节点实际上入队不会超过v次,也即整个最短路径树的更新次数.
5.若对应的点的距离改变了,那么相应的后续与相连的数据必定也要在最短路径上发生变更,这就是实现思想.
#include<vector>
#include<iostream>
#include<queue>
#include<set>
using namespace std;
struct node{
int v;
int l;
node(int v,int l):v(v),l(l){}
};
int main(){
int const INF = 0x3f3f3f3f;
int const MAXN = 510;
//map
vector<node>map[MAXN];
//if in queue;
bool in_que[MAXN];
fill(in_que,in_que+MAXN,false);
//in queue number
int in_count[MAXN];
fill(in_count,in_count+MAXN,0);
//wegiht count;
int w[MAXN];
fill(w,w+MAXN,0);
//wegiht ;
int weight[MAXN];
//distence;
int d[MAXN];
fill(d,d+MAXN,INF);
int num[MAXN];
fill(num,num+MAXN,0);
queue<int> que_map;
set<int> pre[MAXN];
int N,M,C1,C2;
cin>>N>>M>>C1>>C2;
for(int i=0;i<N;i++){
cin>>weight[i];
}
for(int i=0;i<M;i++){
int c1,c2,lenth;
cin>>c1>>c2>>lenth;
map[c1].push_back(node(c2,lenth));
map[c2].push_back(node(c1,lenth));
}
// for(int i=0;i<N;i++){
// int length = map[i].size();
// for(int j=0;j<length;j++){
// cout<<i<<" "<<map[i][j].v<<" "<<map[i][j].l<<endl;
// }
// }
d[C1] = 0;
que_map.push(C1);
w[C1] = weight[C1];
in_que[C1] = true;
in_count[C1] = 1;
num[C1] = 1;
while(!que_map.empty()){
int u = que_map.front();
que_map.pop();
in_que[u] = false;
if(in_count[u]>=N){
break;
}
int lenth = map[u].size();
for(int i=0;i<lenth;i++){
int v = map[u][i].v;
int l = map[u][i].l;
if(d[u]+l<d[v]){
d[v] = d[u]+l;
w[v] = w[u]+weight[v];
num[v]=num[u];
pre[v].clear();
pre[v].insert(u);
if(!in_que[v]){
que_map.push(v);
in_que[v] = true;
in_count[v]++;
}
}else if(d[u]+l==d[v]){
pre[v].insert(u);
num[v] = 0;
set<int>::iterator it = pre[v].begin();
for(;it!=pre[v].end();it++){
num[v]+=num[*it];
}
if(w[u]+weight[v]>w[v]){
w[v] = w[u]+weight[v];
}
}
}
}
cout<<num[C2]<<" "<<w[C2]<<endl;
return 0;
}