天梯赛 L2-001 紧急救援

Preface

太久没写最短路,写个题解记录一下

题意

天梯赛就是太吃细节了

我们重点理解下,题目要求输出什么

  1. 最短路的条数,最大的最短路上的点权和

  2. 最短路路径

求最短路就用dijkstra

  1. 如何求最短路的条数
    我们用一个num来记录到某个点的最短路路径条数,如果v节点可以由u更新最短路,那么\(num[v]=num[u]\),如果从u节点到v节点,也是最短路,那么\(num[v]+=num[u]\)

  2. 如何求最大的最短最短路上的点权和
    用maxt来记录到某个点的最大点权和,更新最短路时同时更新

  3. 如何求最短路路径
    用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;
}
posted @ 2025-04-17 22:20  归游  阅读(10)  评论(0)    收藏  举报