天梯赛 L2-001 紧急救援
Preface
太久没写最短路,写个题解记录一下
题意
天梯赛就是太吃细节了
我们重点理解下,题目要求输出什么
-
最短路的条数,最大的最短路上的点权和
-
最短路路径
求最短路就用dijkstra
-
如何求最短路的条数
我们用一个num来记录到某个点的最短路路径条数,如果v节点可以由u更新最短路,那么\(num[v]=num[u]\),如果从u节点到v节点,也是最短路,那么\(num[v]+=num[u]\) -
如何求最大的最短最短路上的点权和
用maxt来记录到某个点的最大点权和,更新最短路时同时更新 -
如何求最短路路径
用pre记录最短路上节点的前驱,最后不断循环,找到起点,记录路径上的所有点,最后输出
初始化
num[s]=1
maxt[s]=a[s]
Code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
int n,m,s,d;
const int maxn=2e3+10;
int a[maxn];
struct node{
int v,next,w;
}e[maxn*500];
int head[maxn];
int cnt=0;
int maxt[maxn];
void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].next=head[u];
e[cnt].w=w;
head[u]=cnt;
}
bool book[maxn];
int dis[maxn];
vector<int >ans;
int pre[maxn];
int num[maxn];
void dj(){
memset(dis,0x3f3f,sizeof(dis));
dis[s]=0;maxt[s]=a[s];
priority_queue<pii,vector<pii>,greater<pii> >q;
q.push({dis[s],s});num[s]=1;
while(!q.empty()){
int u=q.top().y;
q.pop();
if(book[u]) continue;
book[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
maxt[v]=maxt[u]+a[v];
num[v]=num[u];
pre[v]=u;
q.push({dis[v],v});
}
else if(dis[v]==dis[u]+w){
num[v]+=num[u];
if(maxt[v]<maxt[u]+a[v]){
maxt[v]=maxt[u]+a[v];
pre[v]=u;
}
}
}
}
}
int main(){
cin>>n>>m>>s>>d;
for(int i=0;i<n;++i) cin>>a[i],pre[i]=-1;
for(int i=1;i<=m;++i){
int u,v,w;cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
dj();
for(int i=d;i!=s;i=pre[i]) ans.push_back(i);
ans.push_back(s);
cout<<num[d]<<" "<<maxt[d]<<endl;
reverse(ans.begin(),ans.end());
for(int i=0;i<ans.size();++i){
cout<<ans[i];
if(i!=ans.size()-1) cout<<" ";
}
return 0;
}

浙公网安备 33010602011771号