SPFA 最短路
最短路
什么意思呢
其实就是字面意思喽
解法多样
就只介绍 SPFA 了
每次 用一个 "有意义" 的点 更新与之相连点 的 dis 值
(至于 dis[]数组 dis[i] 表示 源点 到 i 的最短 距离 , dis初始化无穷大)
每次 "有意义" 的更新 就把 被更新点 加入 "有意义点 的 队列" 之中去
(至于 "有意义" 就是 dis 值 变小了,变小了 才有可能 把其他点的 dis 值更新得 更小)
到队列为空时 算法结束 dis 数组 即 源点到各点的最短距离
可以用此图 参考代码 模拟一下
例题
洛谷 P2951 [USACO09OPEN]捉迷藏Hide and Seek
先求出 dis[] 数组
再遍历 dis[] 数组 找出最远 节点 长度 数量
代码
#include<bits/stdc++.h> using namespace std; #define N 20004 #define M 50004 int t=1,s,dis[N],n,m,head[N],to[M<<1],next[M<<1],cnt; bool b[N]; queue<int>que; // "有意义"的队列 int read(){ //读入优化 int ans=0,ch=getchar(); for(;!isdigit(ch);ch=getchar()); for(;isdigit(ch);ch=getchar()) ans=ans*10+ch-'0'; return ans; } int main(){ n=read(),m=read(); for(int i=1,x,y;i<=m;i++){ x=read(),y=read(); next[++cnt]=head[x]; // 链式前向星 to[cnt]=y; head[x]=cnt; next[++cnt]=head[y]; to[cnt]=x; head[y]=cnt; } memset(dis,127/3,sizeof(dis)); // 置一个很大的数 b[1]=1; // 有意义 dis[1]=0; que.push(1); //push for(int u,v;!que.empty();){ u=que.front(); que.pop(); b[u]=0; // 已经取出 变为无意义 for(int j=head[u];j;j=next[j]){ v=to[j]; if(dis[v]>dis[u]+1){ // 是否成功修改 dis[v]=dis[u]+1; if(!b[v]){ // 是否在队列中 b[v]=1; que.push(v); } } } } for(int i=2;i<=n;i++){ // 找答案 if(dis[t]<dis[i]){ t=i; s=1; } else if(dis[t]==dis[i])s++; } printf("%d %d %d",t,dis[t],s); return 0; }