本人也是初学最短路,欢迎交流。
P1462 通往奥格瑞玛的道路
原题链接:传送门
思路:
- 题目有点类似与求最短路的最大边权的最小值,不过这里求的是消耗最大费用的最小值,不难想到二分,这里的边权作为生命值用来判断当前费用能否从联盟中心活着到家。
- 二分答案+dij , 写这道题的时候不小心把前向星的head[u]写成head[i]卡了一个小时,吸取这次教训。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int emmm=1000000005;
const int manx=1e4+5;
const int mamx=1e5+5;
int head[manx],d[manx],c[manx]; //head[]和d[] vis[]作为常规dij必需品 c[]这里存每个城市的消耗费用
bool vis[manx];
priority_queue<pair<int ,int > >q;
int n,m,s,k=0,ans=0;
struct node{
int v,next,w;
}a[mamx];
void add(int u,int v, int w)
{
a[++k].next=head[u];
head[u]=k;
a[k].w=w;
a[k].v=v;
}
bool dij(int x) //最短路判断血量是否为0
{
if(x<c[1]) return 0; //如果连起点的城市都出不去肯定不行
for(int i=1;i<=n;i++) d[i]=1e9,vis[i]=0; //d[i]初始化一定要够大,一开始初始化为0x3f也卡了一会儿
q.push(make_pair(0,1)); //下面是常规的dij操作
d[1]=0;
while(q.size())
{
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].v,w=a[i].w;
if(d[v]>d[u]+w && x>=c[v] &&!vis[v] ) d[v]=d[u]+w,q.push(make_pair(-d[v],v));
}
}
if(d[n]<s) return 1;
else return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w); //注意无向图 要建两条边
add(v,u,w);
}
if(!dij(emmm)){ //首先判断最大费用 如果不行的话比他小的也不行
cout<<"AFK"<<endl;
return 0;
}
int l=1,r=emmm; //二分操作,过段时间会整理总结一下二分
while(l<=r)
{
int mid=(l+r)>>1;
if(dij(mid)) r=mid-1;
else l=mid+1;
}
printf("%d",l);
return 0;
}