题解 P1462 【通往奥格瑞玛的道路】
本题是本人第一个在没有任何人的指导下完成的二分答案的题。
所以发一个题解纪念一下。
题目理解很重要…
而且有一个条件就是,当血量低于0时(其实也是包含0的)就不能到达了。
题目一看是求最大值的最小值或者是求最小值的最大值便科知道要使用二分答案来求解了
下面附上我的代码
#include<bits/stdc++.h>
using namespace std;/*
4 4 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
*/
const int N=11000;
const int M=51000;
const int inf=1e9+7;
struct edge
{
int to,next,val;
}mem[M<<1];//因为是无向图所以要开双向边,所以要开大一倍
int n,m,u,v,cnt=1,b,val,maxn=-1;
int head[M<<1],a[N],d[N];
bool vis[N];
inline void read(int &x)//读入优化
{
x=0;
bool flag=0;
char ch=getchar();
while('0'>ch||ch>'9')
{
if(ch=='-')
flag=1;
ch=getchar();
}
while('0'<=ch&&ch<='9')
{
x=(x<<3)+(x<<1)+ch-'0';//据说两次位运算的速度也要比直接x*10要快
ch=getchar();
}
if(flag)
x=-x;
}
inline void add(int u,int v,int val)//链式前向星存图
{
mem[++cnt].next=head[u];
mem[cnt].to=v;
mem[cnt].val=val;
head[u]=cnt;
}
inline bool spfa(int maxn)//普通的spfa算法求最短路,所经过的所有点的点权都不能大于(<=)maxn
{//具体的spfa的解释就不再这里说了,若有想具体了解spfa的
//请详见[洛谷P3371单元最短路径](https://www.luogu.org/problemnew/show/P3371)
for(int i=1;i<=n;i++)
vis[i]=0,d[i]=inf;
queue<int> q;
while(!q.empty())
q.pop();
d[1]=0,vis[1]=1;
q.push(1);
while(!q.empty())
{
int x=q.front();
q.pop();
if(a[x]>maxn)//点的点权都不能大于(<=)maxn
continue;
for(int e=head[x];e;e=mem[e].next)
{
int to=mem[e].to;
if(a[to]>maxn)//点的点权都不能大于(<=)maxn
continue;
if(d[to]>d[x]+mem[e].val)
{
d[to]=d[x]+mem[e].val;
if(!vis[to])
{
vis[to]=1;
q.push(to);
}
}
}
vis[x]=0;
}
//cout<<"maxn="<<maxn<<" d[n]="<<d[n]<<endl;
if(b>d[n])//如果血量=0或血量<0就不能到达,即掉的最少的血的数目d[n]<b
return 1;//答案不可以是maxn
return 0;//否则答案可以是maxn
}
int main()
{
read(n),read(m),read(b);
for(int i=1;i<=n;i++)
{
read(a[i]);
maxn=max(maxn,a[i]);//确认二分答案的上限
}
for(int i=1;i<=m;i++)
{
read(u),read(v),read(val);
add(u,v,val);//因为是无向图,所以要建立双向的边
add(v,u,val);
}
if(!spfa(maxn))//如果将点权最大的点取上都不能到达,则永远不可能达到
{
puts("AFK");
return 0;
}
int l=0,r=maxn;//二分答案,因为答案的边界可能是[0,maxn]的闭区间
while(l<=r)
{
int mid=l+r>>1;//因为位运算的优先级低于l+r,所以此处打不打括号均可(建议还是打上比较好)
if(!spfa(mid))//最大点权为maxn不能达到
l=mid+1;
else//最大点权为maxn可以达到
r=mid-1;
}
printf("%d\n",l);//输出答案即交费最多的一次的最小值
return 0;
}
本文分享了洛谷P1462【通往奥格瑞玛的道路】题解,作者独立完成的首个二分答案题目。文章详细解析了题目理解的重要性,介绍了如何通过二分答案求解最大值的最小值问题,并附上了完整的代码实现。
410

被折叠的 条评论
为什么被折叠?



