传送门:https://www.luogu.org/problemnew/show/P1462
第一次做了这种求最短路而且要二分答案的。
比较困难吧,但是做了以后也基本领会了其中的道理。
首先二分答案开始写炸了,
这里放上一个模板吧!:
int ans = 0;
while(l<=r)
{
int mid = (l+r)/2;
if(dijkstra(mid))
{
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
cout<<ans<<endl;
这样子的二分答案应该是可以的吧!
然后这个题目直接二分金钱就可以了。
每一次判断加边的时候判断一下该边的金额,小于等于mid就可以。
挺简单的啊!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
const int INF = 1e9+7;
int d[maxn];
int f[maxn];
int n,m,b;
struct node
{
int now;
ll cost;
bool operator<(const node &a)const
{
return cost>a.cost;
}
};
struct edge
{
int to;
ll cost;
};
vector<edge> G[maxn];
bool dijkstra(int x)
{
fill(d,d+maxn,INF);
priority_queue<node> q;
d[1] = 0;
q.push((node){1,d[1]});
while(!q.empty())
{
node tmp = q.top();
q.pop();
if(d[tmp.now]<tmp.cost) continue;
for(int i=0;i<G[tmp.now].size();i++)
{
int v = G[tmp.now][i].to;
if(d[v]>d[tmp.now]+G[tmp.now][i].cost && f[v]<=x)
{
d[v] = d[tmp.now]+G[tmp.now][i].cost;
q.push((node){v,d[v]});
}
}
}
return d[n]<=b;
}
void init()
{
fill(d,d+maxn,INF);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>b;
init();
int l = INF;
int r = -INF;
for(int i=1;i<=n;i++)
{
cin>>f[i];
l = min(l,f[i]);
r = max(r,f[i]);
}
for(int i=0;i<m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if(x==y) continue;
G[x].push_back((edge){y,z});
G[y].push_back((edge){x,z});
}
if(!dijkstra(INF+1))
{
cout<<"AFK"<<endl;
return 0;
}
int ans = 0;
while(l<=r)
{
int mid = (l+r)/2;
if(dijkstra(mid))
{
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
cout<<ans<<endl;
return 0;
}