1   流程

    dist[所有点] = INF
    dist[起始点] = 0

    队列
    起始点入队并标记

    while(队列不空)
    {
        取出队头t
        st[t] = false // spfa的st代表节点是否在队列中 dij的代表是否走过
        用t更新其他所有出点(入队/标记)   
    }   

    判断是否能走

2   code

    int spfa( int u )
    {
        //memset( cnt, 0, sizeof cnt );
        memset( dist, INF, sizeof dist );
        dist[u] = 0;

        queue< int > q;
        q.push( u );
        st[u] = true;
        // for(int i=1;i<=n;i++)
        // {     
        //     st[i]=true;
        //     q.push(i);
        // }
        while( q.size() )
        {
            int t = q.front();
            q.pop();

            st[t] = false;

            for( int i = h[t]; i; i = ne[i] )
            {
                int y = e[i], z = w[i];
                if( dist[y] > dist[t] + z )
                {
                    dist[y] = dist[t] + z;
                    // cnt[y]=cnt[t]+1;
                    // if(cnt[y]>=n) 
                    //      有负环
                    if( !st[y] )
                    {
                        q.push( y );
                        st[y] = true;
                    }
                }
            }
        }

        if( dist[n] > 0x3f3f3f3f /2 )
            return -1;
        else
            return dist[n];
    }

3   spfa判断负环

    cnt[]代表到达当前点最短路的边数
    如果cnt[x] >= n ,说明至少经过n
    条边即n + 1个点, 则至少有一个点
    重复

    cnt[所有点] = 0

    初始时所有点入队

    最短距更新时cnt也更新

    判断是否 > n