1511 基础spfa

题意,求0点到N-1点的来回最短路。

这题是基础spfa题:

坑爹的用了一个下午的时间弄,这题的输入居然要用scanf,为啥没hit提示呢,以后遇到TLE就要考虑是否输入的问题了。

总结下spfa算法,比较高效的算法,有点繁琐,主要是利用了邻接表和队列的形式,与bfs很像。

同时可以利用入队次数到达V判断是否有负环。

spfa优化算法在这题用不着。。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int  maxn=0x3f3f3f3f;
const int  N=1000005;
const int  E=1000005;

struct Edge{
    int pnt;
    int dis;
    int next;
}edge1[E],edge2[E];
int n,e,cur,aver;
int neigh1[N],neigh2[N];
int que[N],mindis[N],front,rear;
bool vis[N];

void spfa(int s,int v)
{
    Edge *edge;
    int *neigh;
    if(v==1)
    {
        edge=edge1;
        neigh=neigh1;
    }
    else
    {
        edge=edge2;
        neigh=neigh2;
    }

    for(int i=0;i<n;i++)
    {
        mindis[i]=maxn;
        vis[i]=false;
    }
    int averge=aver/cur;
    int num=cur;
    front=rear=0;       //s入队
    mindis[s]=0;
    que[rear++]=s;
    while(front!=rear)
    {
        int pre=que[front];
        vis[pre]=false;
        int t=neigh[pre];

        while(t!=-1)
        {
           int pnt= edge[t].pnt;
           if(mindis[pnt]>mindis[pre]+edge[t].dis)
              {
                mindis[pnt]=mindis[pre]+edge[t].dis;
                if(!vis[pnt])
                {
                    vis[pnt]=true;
                    que[rear++]=pnt;

                    if(mindis[que[rear-1]]<mindis[que[front]])//SLF优化算法
                    swap(que[rear-1],que[front]);
                    if(rear==N) rear=0;
                }
              }
            t=edge[t].next;
        }
        if(++front==N)  {front=0;}
    }
}
int main()
{
    int T,begin,end,dis;
    long long sum;
    scanf("%d", &T);
    while(T--)
    {
        cur=0;
        aver=0;
        scanf("%d%d", &n, &e);
        for(int i =0;i<n;i++)neigh1[i]=neigh2[i]=-1;
        for(int i =0;i<e;i++)
        {
            scanf("%d%d%d", &begin, &end, &dis);
            begin--;
            end--;
            aver+=dis;
            edge1[cur].pnt=end;
            edge1[cur].dis=dis;
            edge1[cur].next=neigh1[begin];
            neigh1[begin]=cur;
            edge2[cur].pnt=begin;
            edge2[cur].dis=dis;
            edge2[cur].next=neigh2[end];
            neigh2[end]=cur;
            cur++;
        }

        sum=0;
        spfa(0,1);
        for(int i=1;i<n;i++)sum+=mindis[i];
        spfa(0,2);
        for(int i=1;i<n;i++)sum+=mindis[i];
        printf("%lld\n", sum);
    }
    return 0;
}


 

原文地址:https://www.cnblogs.com/amourjun/p/5134223.html