1. 程式人生 > >SPFA 最短路

SPFA 最短路

有意 using span 修改 一個 push family memset spfa

GeneralLiu

最短路

什麽意思呢

其實就是字面意思嘍

解法多樣

就只介紹 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; }

SPFA 最短路