P1462 通往奥格瑞玛的道路 Djk+二分

P1462 通往奥格瑞玛的道路

最近在写最短路的题,补一补寒假集训图论部分的知识,大概花了2-3周时间来学最短路,现在算是能做一些相对来说基础一些的题,算是刚刚入门图论吧...

这道题刚开始我连题意都没读懂,想了很长时间也没想明白,就想着去看看题解对于题意的解释,然后就大概明白题意了,这道题原来问的是在能血量正常通过的道路中找出单笔交费的最大值最少为多少钱?(可能解释的还是比较奇怪...但这就是二分答案的暗示, 可以多看几遍这句话) 然后知到是二分答案的题之后就可以通过二分来规定每次设定的单笔交费的最大值最少的值, 然后通过djk来判断是否符合条件, 以此来进行解题, 接下来放代码

#include<bits/stdc++.h>
#define ll long long
#define PII pair<ll, ll>
#define inf 0x3f3f3f3f
using namespace std;

struct point{
	ll to, next, w;
}point[1000000];
bool vis[1000000];//vis数组用来标记
ll n, m, b, f[1000000], number, l, r, dis[1000000], head[1000000];
//dis数组用来以扣除血量来进行最短路
void add(ll u, ll v, ll w){
	point[number].to=v, point[number].w=w, point[number].next=head[u];
	head[u]=number;
	number++;
}
bool dijkstra(ll x){
	priority_queue<PII, vector<PII>, greater<PII>>q;
	for(ll i=1; i<=n; i++){
		dis[i]=inf;
		vis[i]=0;//交了三发,一直wa,后来发现是vis没初始化。。。
	} 
	dis[1]=0;
	q.push({1, 1});
	while(!q.empty()){
		ll num=q.top().second;
		q.pop();
		if(vis[num])
			continue ;
		vis[num]=true;
		for(ll k=head[num]; k!=-1; k=point[k].next){
			if(f[point[k].to]<=x&&dis[point[k].to]>dis[num]+point[k].w){
				dis[point[k].to]=dis[num]+point[k].w;
				q.push({dis[point[k].to], point[k].to});
			}
		}
	}
	if(dis[n]<=b)
		return 1;
	return 0;
}
int main(){
	scanf("%lld %lld %lld", &n, &m, &b);
	for(ll i=1; i<=n; i++){
		scanf("%lld", &f[i]);
		r=max(r, f[i]);
	}
//链式前向星构图
	for(ll i=1; i<=2*m; i++)
		head[i]=-1;
	for(ll i=1; i<=m; i++){
		ll u, v, w;
		scanf("%lld %lld %lld", &u, &v, &w);
		add(u, v, w);
		add(v, u, w);
	}

	l=f[1];
	if(dijkstra(r)){
		while(l<r){
			ll mid=(l+r)>>1;
			if(dijkstra(mid))
				r=mid;
			else
				l=mid+1;
		}
		printf("%lld\n", l);
	}
	else
		printf("AFK\n");
	return 0;
} 

这里是堆优化的djk, 时间方面是n log n的复杂度, 不会被卡

本来想在写一道洛谷题单最短路的绿题, 结果想了半天也没头绪, 看了眼题签可能是dp就先撤退了...

最近打算开学dp(1月份寒假集训的噩梦之一...) 学完dp感觉大的知识面就拓展的差不多了, 就继续往细拓展知识面了, 希望dp能少折磨我点...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值