P3371 【模板】单源最短路径 SPFA优化 dijkstra堆优化

来源:互联网 发布:数据保险箱 编辑:程序博客网 时间:2024/05/17 23:00

1.SPFA加优化

#include<cstdio>#include<cstring>#include<deque>using namespace std;const int N=10000+5,M=500000+5; int n,m,s;int to[M],head[N],w[M],nxt[M],etot;int dis[N];void adde(int u,int v,int c){    to[++etot]=v;    nxt[etot]=head[u];    w[etot]=c;    head[u]=etot;}void SPFA(){    bool exi[N];    memset(exi,0,sizeof(exi));//  memset(dis,32,sizeof(dis));    for(int i=0;i<=n;i++)    dis[i]=2147483647;//  printf("DIS:%d\n",dis[0]);    deque<int> q;    dis[s]=0;    q.push_back(s);    while(!q.empty()){        int u=q.front();q.pop_front();        exi[u]=0;        for(int i=head[u];i;i=nxt[i]){            int v=to[i];            if(dis[v]>dis[u]+w[i]){                dis[v]=dis[u]+w[i];                if(!exi[v]){                    exi[v]=1;                    if(dis[v]<dis[u]) q.push_front(v);                    else q.push_back(v);                }            }        }    }}int main(){    scanf("%d%d%d",&n,&m,&s);    for(int i=1;i<=m;i++){        int u,v,c;        scanf("%d%d%d",&u,&v,&c);        adde(u,v,c);    }    SPFA();    for(int i=1;i<=n;i++)        printf("%d ",dis[i]);    return 0;}

下图是加了优化的SPFA和不加优化的SPFA的效率比较:
上面的是没加的,下面的是加了的
这里写图片描述
2.dijkstra堆优化

/*注意该算法要求图中不存在负权边。迪杰斯特拉算法:入队一个点,更新这个点连向的点。更新完毕后 ,找到最短的点,再次更新 */#include<cstdio>#include<cstring>#include<queue>using namespace std;const int N=10000+5,M=500000+5; int n,m,s;int to[M],head[N],w[M],nxt[M],etot;int dis[N];typedef pair<int,int> pii; priority_queue<pii,vector<pii>,greater<pii> >q;void adde(int u,int v,int c){    to[++etot]=v;    nxt[etot]=head[u];    w[etot]=c;    head[u]=etot;}void dijkstra(){    bool exi[N];    memset(exi,0,sizeof(exi));    for(int i=0;i<=n;i++)    dis[i]=2147483647;    q.push(make_pair(0,s));    dis[s]=0;    while(!q.empty()){        pii x=q.top();q.pop();        int u=x.second;        for(int i=head[u];i;i=nxt[i]){            int v=to[i];            if(dis[v]>dis[u]+w[i]){//一个点可能被重复入队                 dis[v]=dis[u]+w[i];                q.push(make_pair(dis[v],v));            }        }    }}int main(){    scanf("%d%d%d",&n,&m,&s);    for(int i=1;i<=m;i++){        int u,v,c;        scanf("%d%d%d",&u,&v,&c);        adde(u,v,c);    }    dijkstra();     for(int i=1;i<=n;i++)        printf("%d ",dis[i]);    return 0;}

这里写图片描述
(它比没加优化的SPFA只快那么一点点)

什么时候用SPFA,什么时候用dijkstra呢?

如果是稠密图,Dijkstra+heap比SPFA快。稀疏图则SPFA更快。SPFA可以有SLF和LLL两种优化,SLF就是d比队头小就插入队头,否则插入队尾。

原创粉丝点击