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能少折磨我点...