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;
}

 

posted @ 2017-05-06 20:35  GeneralLiu  阅读(198)  评论(0编辑  收藏  举报