PTA 天梯 紧急救援 Dijkstra 堆优化

题目链接
在这里插入图片描述
D i j k s t r a Dijkstra Dijkstra堆优化的解法
不会请自行百度

#include <bits/stdc++.h>
#define mes(a, b)  memset(a, b, sizeof a)
#define pb push_back
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e3 + 20;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
using namespace std;
int head[maxn],vis[maxn],tot = 0;
ll dis[507];
ll b[507];   // 每个点的队伍
ll num[507]; //记录每个点最短路径条数
ll pre[1007];  //记录前驱
ll cnt[507];  //记录最短路一样的最大流量
int n,m,s,e;
struct node{
	int to,ne;
	ll w;
}edge[500007];
void addedge(int u,int v,ll w){
	edge[tot].to = v;
	edge[tot].w = w;
	edge[tot].ne = head[u];
	head[u] = tot++;
}
struct HeapNode{
	ll dis;int u;
	HeapNode(ll dis = 0,int u = 0) : dis(dis),u(u){}
	bool operator <(const HeapNode& a)const{
		return dis > a.dis;
	}
}a;

void dijk(int x){
	for(int i = 1;i <= n;i++) dis[i] = (ll)INF;
	dis[x] = 0;
	priority_queue<HeapNode>pq;
	while(!pq.empty()) pq.pop();
	pq.push(HeapNode(0,x));
	while(!pq.empty()){  //first distance second point
		a = pq.top(); pq.pop();
		int u = a.u;

		if(vis[u]) continue;
		vis[u] = 1;

		for(int i = head[u];i != -1;i = edge[i].ne){  //扫描出边
			int v = edge[i].to;ll w = edge[i].w;  //v: 出边  w: 权值
			if(dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;
				pq.push(HeapNode(dis[v],v));
				num[v] = num[u];
				pre[v] = u;
				cnt[v] = cnt[u] + b[v];
			}
			else if(dis[v] == dis[u] + w)
            {
                if(cnt[v] < cnt[u] + b[v])
                {
                    pre[v] = u;
                    cnt[v] = cnt[u] + b[v];
                }
                num[v] += num[u];
            }
		}
	}
}
void init(){
	mes(head,-1);tot = 0;
}

int main(){
	scanf(" %d %d %d %d",&n,&m,&s,&e);
    s++; e++;
    for(int i = 1; i <= n; i++) scanf(" %lld",&b[i]);
    init();
	for(int i = 1;i <= m;i++){
		int u,v;ll w;
		scanf("%d %d %lld",&u,&v,&w);
        u++; v++;
		addedge(u,v,w);
		addedge(v,u,w);
	}
	num[s] = 1;
	cnt[s] = b[s];
	dijk(s);
	printf("%lld %lld\n",num[e],cnt[e]);

	vector<int>path;
	for(int i = e; i != s; i = pre[i]) path.push_back(i-1);
	path.push_back(s-1);
	for(int i = path.size()-1; i >= 0; i--)
        if(i != path.size()-1) printf(" %d",path[i]);
        else printf("%d",path[i]);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸愉信奥

谢谢亲的支持,我会继续努力啦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值