zoukankan      html  css  js  c++  java
  • SPFA + 静态邻接表 模板

      SPFA — shotest path faster algorithm,是一个效率很高的求最短路径的算法,也可以说是bellman-ford算法的优化版。

          具体做法是先把起点放入一个队列中。每次取出队顶元素,并pop,看跟该点相邻的其他点是否能够松弛,如果可以松弛,改变数值,如果该点不在队列中,则把能该点push到队列中,直到队列为空。

          为了速度更快,可以用邻接表来存储,这样,找与起点相邻的点的速度就会很快!

         若要判负环路,则记录一个点的入队次数,若超过边数,则有负权环。

         自己用SPFA+静态邻接表写的hdu_2544:可以用作模板(实际上只要理解了是不需要模板的)

    代码
    #include <iostream>
    #include
    <queue>
    using namespace std;
    const long lmax = 1000000000;
    const long edge_maxn = 10005; //边的最大上限
    const long point_maxn = 105; //点的最大上限
    struct node
    {
    /*node存储边,一个edge代表一条边*/
    int v; //终点位置
    int w; //权值
    int next; //同一起点的下一条边存储在edge数组中的位置(理解了这个静态邻接表就可以了)
    }edge[edge_maxn];
    int pre[point_maxn]; //以该点为起点的第一条边存储在edge数组中的位置
    int n; //点的数量
    int m; //边的数量
    queue<int> Q;
    int dirs[point_maxn];
    bool vis[point_maxn];
    void Init()
    {
    memset(pre,
    -1,sizeof(pre));
    int Index = 1;
    int i,j,flag;
    int x,y,w;
    for(i=0;i<m;i++)
    {
    scanf(
    "%d%d%d",&x,&y,&w);
    for(flag=0,j=pre[x];j!=-1;j=edge[j].next)
    {
    //重边的情况
    if(y == edge[j].v)
    {
    if(w < edge[j].w)
    edge[j].w
    = w;
    flag
    = 1;
    break;
    }
    }
    if(flag == 1)
    continue;
    edge[Index].v
    = y;
    edge[Index].w
    = w;
    edge[Index].next
    = pre[x]; //保存x起点的上一条边在edge数组中的位置
    pre[x] = Index++; //位置更新
    swap(x,y);
    edge[Index].v
    = y;
    edge[Index].w
    = w;
    edge[Index].next
    = pre[x];
    pre[x]
    = Index++;
    }
    }
    void print(int end)
    {
    printf(
    "%d\n",dirs[end]);
    }
    void SPFA()
    {
    int start = 1;
    int end = n;
    while(!Q.empty())
    {
    Q.pop();
    }
    memset(vis,
    0,sizeof(vis));
    fill(dirs,dirs
    +point_maxn,lmax);

    dirs[start]
    = 0;
    vis[start]
    = 1;
    Q.push(start);
    while(!Q.empty())
    {
    int top = Q.front(); //边的起点
    Q.pop();
    vis[top]
    = 0;
    for(int j=pre[top];j!=-1;j=edge[j].next)
    {
    int e = edge[j].v; //边的终点
    if(dirs[e] > edge[j].w + dirs[top])
    {
    dirs[e]
    = edge[j].w + dirs[top];
    if(!vis[e])
    {
    Q.push(e);
    vis[e]
    = 1;
    }
    }
    }
    }
    print(end);
    }
    int main()
    {
    while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0))
    {
    Init();
    SPFA();
    }
    //system("pause");
    return 0;
    }
  • 相关阅读:
    set集合 深浅拷贝
    2015 ACM/ICPC Asia Regional Changchun Online Pro 1005 Travel (Krsukal变形)
    2015 ACM/ICPC Asia Regional Changchun Online Pro 1002 Ponds(拓扑排序+并查集)
    Codeforces Round #319 (Div. 2) B Modulo Sum (dp,鸽巢)
    Codeforces Round #319 (Div. 2) C Vasya and Petya's Game (数论)
    UVA 11468 Substring (AC自动机)
    UVA11019 Matrix Matcher (AC自动机)
    UVALive 4670 Dominating Patterns (AC自动机)
    UVALive 3026 Period (KMP算法简介)
    UVA 11732 strcmp() Anyone (Trie+链表)
  • 原文地址:https://www.cnblogs.com/silencExplode/p/1876782.html
Copyright © 2011-2022 走看看