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;
}
spfa +dfs 满分实现
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<set>
using namespace std;
const int MAXN = 10000;
int N,M;
const int INF = 0xf3f3f3f;
int weight[MAXN];
struct node{
int to,len,rec;
node(){}
node(int to,int len,int rec):to(to),len(len),rec(rec){};
};
int innum[MAXN];
bool inque[MAXN];
int dist[MAXN];
set<int> pre[MAXN];
vector<node> map_[MAXN];
void add_edge(int a, int b, int cost){
map_[a].push_back(node(b,cost,map_[b].size()));
map_[b].push_back(node(a,cost,map_[a].size()-1));
}
vector<int> temp_path;
int cal(vector<int> path){
int ans = 0;
for(int i = path.size()-1; i>=0;i--){
ans += weight[path[i]];
}
return ans;
}
int max_ = -1;
int pathNum = 0;
void dfs_out(int start,int end){
if(start == end){
temp_path.push_back(start);
int ans = cal(temp_path);
pathNum++;
if(ans > max_){
max_ = ans;
}
temp_path.pop_back();
return;
}
temp_path.push_back(end);
set<int>::iterator it = pre[end].begin();
for(;it!=pre[end].end();it++){
// printf("%d\n",*it);
dfs_out(start,*it);
}
temp_path.pop_back();
}
bool spfa(int start){
fill(dist,dist+N,INF);
memset(inque,0,sizeof(inque));
memset(innum,0,sizeof(innum));
dist[start] = 0;
inque[start] = 1;
innum[start] = 1;
queue<node> que;
que.push(node(start,0,0));
while(!que.empty()){
node temp = que.front(); que.pop();
inque[temp.to] = false;
for(int i=0;i<map_[temp.to].size();i++){
node nnode = map_[temp.to][i];
if(dist[nnode.to]> dist[temp.to] + nnode.len){
dist[nnode.to] = dist[temp.to] + nnode.len;
pre[nnode.to].clear();
pre[nnode.to].insert(temp.to);
if(inque[nnode.to]) continue;
inque[nnode.to] = 1;
que.push(nnode);
if(innum[nnode.to]>= N-1) return false;
innum[nnode.to]++;
}else if(dist[nnode.to]== dist[temp.to] + nnode.len){
pre[nnode.to].insert(temp.to);
}
}
}
return true;
}
int main(){
int start,end;
scanf("%d%d%d%d",&N,&M,&start,&end);
for(int i=0;i<N;i++)
scanf("%d",&weight[i]);
for(int i=0;i<M;i++){
int a,b,cost;
scanf("%d%d%d",&a,&b,&cost);
add_edge(a,b,cost);
}
spfa(start);
dfs_out(start,end);
printf("%d %d\n",pathNum,max_);
return 0;
}