二分模板+diji算法
#include<bits/stdc++.h>
using namespace std;
const int N=10001;
long long f[N];
vector<pair<int,long long>>vec[N];
priority_queue<pair<long long ,int>>que;
int n,m;long long b;int mx;
int vis[N];long long dis[N];
int check(int x)
{
if(f[1]>x)return 0;
for(int i=1;i<=n;i++)
{
vis[i]=0;
dis[i]=1e18;
}
dis[1]=0;
que.push(make_pair(0,1));
while(!que.empty())
{
int u=que.top().second;
que.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<vec[u].size();i++)
{
int v=vec[u][i].first;
if(f[v]>x)continue;
long long w=vec[u][i].second;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
que.push(make_pair(-dis[v],v));
if(v==n)
{
if(dis[v]>b)return 0;
else return 1;
}
}
}
}
return 0;
}
int main()
{
cin>>n>>m>>b;
int ai,bi,ci;
for(int i=1;i<=n;i++)
{
cin>>f[i];
if(f[i]>mx)mx=f[i];
}
for(int i=1;i<=m;i++)
{
cin>>ai>>bi>>ci;
vec[ai].push_back(make_pair(bi,ci));
vec[bi].push_back(make_pair(ai,ci));
}
long long ans=-1,l=1,r=mx;
while(l<=r)
{
long long mid=(l+r)/2;
if(check(mid)){ans=mid;r=mid-1;}
else l=mid+1;
}
if(ans==-1)cout<<"AFK"<<endl;
else cout<<ans<<endl;
}
check使用diji实现,优先级队列真的很方便。
弹出顶上节点(diji中距离源点路径最短),对链接的每个子节点进行更新,并加入到优先级队列中。
注意:1.有向边or无向边
2.默认大根堆,加入的是负的距离
diji不可处理负边权。
以下为bellman-floyd算法,可处理负边权,环等情况。
def bellman_ford(graph, V, source):
# 初始化距离数组
dist = [float("inf")] * V
dist[source] = 0
# 进行 V-1 次松弛操作
for _ in range(V - 1):
for u, v, weight in graph:
if dist[u] != float("inf") and dist[u] + weight < dist[v]:
dist[v] = dist[u] + weight
# 检查是否存在负权环
for u, v, weight in graph:
if dist[u] != float("inf") and dist[u] + weight < dist[v]:
print("Graph contains negative weight cycle")
return None
return dist