- zz操作:一开始把最短路径条数理解成了最短的路径有几条路,wa到底,特此记录一下
- 仔细一看才是最短路径一共有几条,样例成功骗了我 23333
解题思路: SPFA跑出最短路,prev数组记录路径,llen数组记录到达每个结点的累加人数。
最后dfs跑一下,找出所有的最短路即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define IO ios_base::sync_with_stdio(0),cin.tie(0)
#define fin freopen("in.txt","r",stdin)
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const double PI = 4*atan(1.0);
int n,m,s,d;
struct node
{
int to;
int nex;
int w;
int len;
}edge[505*505];
bool vis[maxn];
int head[maxn];
int cnt = 0;
int dist[maxn];
void addedge(int u,int v,int w)
{
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].nex = head[u];
edge[cnt].len = 1;
head[u] = cnt;
cnt++;
}
int llen[maxn];
int pnum[maxn];
int prevz[maxn];
int step[maxn];
int tot;
void spfa()
{
queue<int> q;
vis[s] = 0;
q.push(s);
memset(dist,INF,sizeof(dist));
dist[s] = 0;
llen[s] = pnum[s];
prevz[s] = -1;
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u];~i;i = edge[i].nex){
int v = edge[i].to;
if(dist[v] > dist[u]+edge[i].w || (dist[v] == dist[u]+edge[i].w && llen[v]<llen[u]+pnum[v])){
dist[v] = dist[u]+edge[i].w;
llen[v] = llen[u]+pnum[v];
prevz[v] = u;
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
}
int res = 0;
void dfs(int p)
{
if(p == d){
res++;
return;
}
for(int i = head[p];~i;i=edge[i].nex){
int v = edge[i].to;
if(!vis[v] && dist[v] == dist[p]+edge[i].w){
vis[v] = true;
dfs(v);
vis[v] = false;
}
}
}
int main()
{
// fin;
IO;
memset(head,-1,sizeof(head));
cin>>n>>m>>s>>d;
for(int i=0;i<n;i++) cin>>pnum[i];
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
addedge(u,v,w);
addedge(v,u,w);
}
spfa();
int tmp = prevz[d];
step[tot++] = d;
while(tmp!=-1){
step[tot++] = tmp;
tmp = prevz[tmp];
}
memset(vis,0,sizeof(vis));
dfs(s);
cout<<res<<" "<<llen[d]<<endl;
for(int i=tot-1;i>=0;i--){
if(i == tot-1) cout<<step[i];
else cout<<" "<<step[i];
}
return 0;
}