比较全的一个博客
https://www.cnblogs.com/wozuishuaiwozuiniu6/p/13178762.html
spfa
SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE)。
再被题面军搞懵一阵子后发现这貌似是一个求最大值最小的问题(还真是)。
哦,找上界嘛,使这个上界在能跑到n点的情况下尽可能的小,当然上界就是f [i] 啦。可以加一个mon数组,排遍序,二分比较方便。
二分答案套模板,把judge换成spfa版,具体看代码,框架是二分答案的架子,主体是spfa。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
queue <int> que;
struct Edge{
int next;
int to;
int key;
}edge[100005];
int cnt=0,head[50001],n,m,b,f[50001],mon[50001],r,l,mid,ans;
long long dis[50001];
bool vis[50001];
int read()
{
int r=0,k=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
return r*k;
}
void add(int x,int y,int z)
{
++cnt;
edge[cnt].next=head[x];
head[x]=cnt;
edge[cnt].to=y;
edge[cnt].key=z;
}
bool spfa(int sj)
{
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1]=0;
vis[1]=1;
que.push(1);
while(!que.empty())
{
int x=que.front();
que.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
int will=edge[i].to;
if(f[will]>sj) continue;
if(dis[x]+edge[i].key<dis[will])
{
dis[will]=dis[x]+edge[i].key;
if(!vis[will])
{
vis[will]=1;
que.push(will);
}
}
}
}
if(dis[n]>=b||dis[n]==dis[0]) return 0;
else return 1;
}
int main()
{
n=read();
m=read();
b=read();
for(int i=1;i<=n;i++) mon[i]=f[i]=read();
sort(mon+1,mon+1+n);
for(int i=1;i<=m;i++)
{
int x,y,z;
x=read();
y=read();
z=read();
add(x,y,z);
add(y,x,z);
}
l=1,r=n;
if(!spfa(1000000001))
{
cout<<"AFK"<<endl;
return 0;
}
while(l<=r)
{
mid=(l+r)>>1;//二分金钱
if(spfa(mon[mid]))//看看在此情况下,血量是否允许
{
r=mid-1;
ans=mon[mid];
}
else l=mid+1;
}
cout<<ans<<endl;
return 0;
}
迪杰斯特拉
时间复杂是 O(n2+m)O(n2+m), nn 表示点数,mm 表示边数
int g[N][N]; // 存储每条边
int dist[N]; // 存储1号点到每个点的最短距离
bool st[N]; // 存储每个点的最短路是否已经确定
// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < n - 1; i ++ )
{
int t = -1; // 在还未确定最短路的点中,寻找距离最小的点
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
// 用t更新其他点的距离
for (int j = 1; j <= n; j ++ )
dist[j] = min(dist[j], dist[t] + g[t][j]);
st[t] = true;
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}