L2-001 紧急救援 (25分)
与一般最短路题目相比,多了节点的权重以及输出路径。
在简单的djs基础上,多了到达每个节点的最大救援数以及更新路径:倒序更新,使用pre函数,如在pre[s(终点)]可能的值中找到最大救援的路径,这样就不仅满足>关系更新,=时也要更新。
inline void djs()
{
for(re int i=1;i<=n;i++)dis[i]=2147483647;
dis[s]=0;
priority_queue<node>Q;//初始化
node a ={s,0};
Q.push(a);//第一个node
while(!Q.empty())
{
node fr=Q.top();Q.pop();
int u=fr.u,d=fr.d;
//取出并记录
if(d!=dis[u])continue;//避免处理无用数据,也就是dis[u]已经更新,之前未更新数据直接出栈,比如有一组数据 2 5,但是后面又入栈一组数据2 3,则2 5是无用数据
for(re int j=0;j<g[u].size();j++)
{
int tm=g[u][j].to;
if(dis[u]+g[u][j].cost<dis[tm])
{
dis[tm]=dis[u]+g[u][j].cost;
Q.push((node){tm,dis[tm]});
}
}
}
}
#include<bits/stdc++.h>
#define intn long long
#define ls(k) (k)<<1
#define inf 2147483647
#define re register
#define rs(k) (k)<<1|1
#define _0for(i, a) for(int i = 0; i < (a); ++i)
#define _1for(i, a) for(int i = 1; i <=(a); ++i)
#define lowbit(x) ((x)&(-x))
#define debug(x) \
(void)(cerr << "L" << __LINE__\
<< " : " << #x << " = " \
<< (x) << endl )
using namespace std;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct edge
{
int to,cost;
};
struct node
{
int u,d;
bool operator <(const node&rhs)const
{
return d>rhs.d;
}
};
int n,dis[20000],s,m,d;
vector<edge>g[50000];
int road[20000];
int jy[200000];
int pre[200000];
int gejy[200000];
void djs()
{
for(re int i=0;i<=n;i++)dis[i]=inf;
dis[s]=0;
priority_queue<node>Q;
node a={s,0};
Q.push(a);
while(!Q.empty())
{
node fr=Q.top();
Q.pop();
int u=fr.u,d=fr.d;
if(road[u]==0)road[u]=1;
if(d!=dis[u])continue;
for(re int j=0;j<g[u].size();j++)
{
int tm=g[u][j].to;
if(dis[u]+g[u][j].cost<dis[tm])
{
dis[tm]=dis[u]+g[u][j].cost;
Q.push((node){tm,dis[tm]});
road[tm]=road[u];
pre[tm]=u;
gejy[tm]=gejy[u]+jy[tm];
}
else if(dis[u]+g[u][j].cost==dis[tm])
{
road[tm]+=road[u];
if(gejy[tm]<gejy[u]+jy[tm])//找到最大救援数的节点。
{
pre[tm]=u;
}
gejy[tm]=max(gejy[tm],gejy[u]+jy[tm]);
}
}
}
}
void outpath()
{
stack<int> st;
st.push(d);
for(int i=pre[d];i!=-1;i=pre[i])
{
st.push(i);
}
int x=st.top();
printf("%d",x);
st.pop();
while(!st.empty())
{
int x=st.top();
printf(" %d",x);
st.pop();
}
}
main(void)
{
cin>>n>>m>>s>>d;
fill(pre,pre+10000,-1);
for(int i=0;i<n;i++)
{
cin>>jy[i];
gejy[i]=jy[i];
}
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back(edge{b,c});
g[b].push_back(edge{a,c});
}
djs();
printf("%d %d\n",road[d],gejy[d]);
outpath();
}