L2-001 紧急救援(最短路)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了L2-001 紧急救援(最短路)相关的知识,希望对你有一定的参考价值。

题目链接

https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840

思路

我们只需要在跑迪杰斯特拉最短路的时候注意一下松弛操作即可,我们定义 d i s [ i ] dis[i] dis[i] 表示从起点 s s s i i i 点的最短路径, s u m [ i ] sum[i] sum[i] 表示从 s s s 点到 i i i 点的最多的救援队数量, c n t [ i ] cnt[i] cnt[i] 表示从 s s s 点到 i i i 点的最短路的条数, p r e [ i ] pre[i] pre[i] 表示在最优路径下 i i i 点的上一个点的位置

  • 如果dis[v] > dis[u] + w,那么我们就要更新 d i s [ v ] = d i s [ u ] + w dis[v] = dis[u] + w dis[v]=dis[u]+w s u m [ v ] = s u m [ u ] + a [ v ] sum[v] = sum[u] + a[v] sum[v]=sum[u]+a[v] c n t [ v ] = c n t [ u ] cnt[v] = cnt[u] cnt[v]=cnt[u] p r e [ v ] = u pre[v] = u pre[v]=u,并且将v点放入队列
  • 如果dis[v] == dis[u] + w,那么我们就要更新 c n t [ v ] + = c n t [ u ] cnt[v] += cnt[u] cnt[v]+=cnt[u] ,因为我们可以从另外一个地方走到 v v v ,如果 s u m [ u ] + a [ v ] > s u m [ v ] sum[u] + a[v] > sum[v] sum[u]+a[v]>sum[v] 那么我们就要更新 s u m [ v ] = s u m [ u ] + a [ v ] sum[v] = sum[u] + a[v] sum[v]=sum[u]+a[v] 且更新 v v v 点的上一个节点为 p r e [ v ] = u pre[v] = u pre[v]=u (因为我们要选择最优路径)

代码

#include<bits/stdc++.h>
using namespace std;
//----------------自定义部分----------------
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f

int dx[4] = -1, 0, 1, 0, dy[4] = 0, 1, 0, -1;

ll ksm(ll a,ll b) 
	ll ans = 1;
	for(;b;b>>=1LL) 
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	
	return ans;


ll lowbit(ll x)return -x & x;

const int N = 2e6+10;
//----------------自定义部分----------------

struct Node
	int v,w;
;

int t,n,m,s,d,q,a[N];
bool vis[N];
vector<Node> E[N];
int dis[N],sum[N],cnt[N],pre[N];

void DJ()
	priority_queue<PII,vector<PII>,greater<PII> > que;
	memset(dis,0x3f,sizeof dis);
	memset(pre,-1,sizeof pre);
	que.push(0,s);
	dis[s] = 0;
	cnt[s] = 1;
	sum[s] = a[s];
	while(!que.empty())
		int u = que.top().second;
		que.pop();
		if(vis[u]) continue;
		vis[u] = true;
		for(int i = 0,l = E[u].size();i < l; ++i) 
			int v = E[u][i].v,w = E[u][i].w;
			if(dis[v] > dis[u] + w)
				dis[v] = dis[u] + w;
				sum[v] = sum[u] + a[v];
				cnt[v] = cnt[u];	
				pre[v] = u;
				que.push(dis[v],v);
			 else if(dis[v] == dis[u] + w)
				cnt[v] += cnt[u];
				if(sum[u] + a[v] > sum[v]) 
					sum[v] = sum[u] + a[v];
					pre[v] = u;
				
				
		
	


void print(int p)
	stack<int> S;
	while(p != -1) 
		S.push(p);
		p = pre[p];
	
	while(S.size() != 1)
		cout<<S.top()-1<<" ";
		S.pop();
	
	if(S.size()) 
		cout<<S.top()-1<<endl;
		S.pop();
	
	


void slove()
	cin>>n>>m>>s>>d;
	s++,d++;
	for(int i = 1;i <= n; ++i) cin>>a[i];
	int u,v,w;
	for(int i = 0;i < m; ++i)
		cin>>u>>v>>w;
		u++,v++;
		E[u].push_back(v,w);
		E[v].push_back(u,w);
	
	DJ();
	cout<<cnt[d]<<" "<<sum[d]<<endl;
	print(d);


int main()

	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	t = 1;
	while(t--)
		slove();
	
	
	return 0;

以上是关于L2-001 紧急救援(最短路)的主要内容,如果未能解决你的问题,请参考以下文章

L2-001. 紧急救援(PAT)~最短路应用

L2-001. 紧急救援

L2-001. 紧急救援

L2-001. 紧急救援

天梯赛 L2-001 紧急救援

PTA天梯赛L2