洛谷P1462通往奥格瑞玛的道路
设某条从 1 到 n 的路径里,经过单个城时所花费的费用的最大值为 T,则这道题我们要求的就是在所有可能路径里面,选T最小的情况。
我们可以先发现,对于任何一个可能合题的T,值必须要满足一点:在去掉所有收费比T大的点去掉后,还是存在一条路使可以从 1 到 n 。
那么这样就形成了检验条件,我们就可以将二分法使用到该题中。可以先把所有点的收费排序,然后从用二分法枚举,最终得到答案。一开始为了检验原图中是否存在 1 到 n 的通路,可以先检验收费最大的点的收费值,这样就相当于在不去掉任何点的情况下检验了原图。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<ll,int> P;
const ll inf=10000000001000000;
struct imf
{
int to,value;
};
int n,m,hp,tot=0;
int b[10010],c[10010],vis[10010];
ll d[10010];
vector<imf>Q[10010];
priority_queue<P,vector<P>,greater<P> >G;
bool check(int x)
{
if(x<b[1]||x<b[n])return false;
int i;
for(i=1;i<=n;i++)d[i]=inf;
for(i=1;i<=n;i++)
{
if(b[i]>x)vis[i]=true;
else vis[i]=false;
}
d[1]=0;
G.push(make_pair(0,1));
while(!G.empty())
{
P tmp=G.top();
G.pop();
if(tmp.first<d[tmp.second])continue;
for(int s=0;s<Q[tmp.second].size();s++)
{
imf f=Q[tmp.second][s];
if(vis[f.to])continue;
if(d[f.to]>d[tmp.second]+f.value)
{
d[f.to]=d[tmp.second]+f.value;
G.push(make_pair(d[f.to],f.to));
}
}
}
if(d[n]<=hp)return true;
else return false;
}
int main()
{
int i,j,k,t,ans;
scanf("%d%d%d",&n,&m,&hp);
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
c[i]=b[i];
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&j,&k,&t);
if(j==k)continue;
Q[j].push_back((imf){k,t});
Q[k].push_back((imf){j,t});
}
sort(c+1,c+n+1);
int l=1,r=n,mid;
if(!check(c[n]))
{
printf("AFK\n");
return 0;
}
ans=c[n];
while(l<=r)
{
mid=(l+r)>>1;
if(check(c[mid]))
{
ans=c[mid];
r=mid-1;
}
else l=mid+1;
}
printf("%d\n",ans);
}