zoukankan      html  css  js  c++  java
  • 【模板】单源最短路径*

    题目描述

    如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

    输入输出格式

    输入格式:

    第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

    接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

    输出格式:

    一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

    输入输出样例

    输入样例#1:
    4 6 1
    1 2 2
    2 3 2
    2 4 1
    1 3 5
    3 4 3
    1 4 4
    输出样例#1:
    0 2 4 3

    说明

    时空限制:1000ms,128M

    数据规模:

    对于20%的数据:N<=5,M<=15

    对于40%的数据:N<=100,M<=10000

    对于70%的数据:N<=1000,M<=100000

    对于100%的数据:N<=10000,M<=500000

    样例说明:

    思路:SPFA or Dijkstra

    此题是有向边!!!(然而我并没有被这里坑)

    SPFA

    初始化最短路径表;

    源点入队;

    取出队首点;

    枚举取出点的边;

    如果能松弛,就松弛,并把被松弛的点加入队列;

    如此循环直到队列为空。

    另外,根据2183ms的亲测,使用优先队列应该没有明显优化效果(可能更稳定了,我不太懂)。

    Dijkstra

    初始化最短路径表;

    源点标记;

    用源点的边松弛;

    寻找距离最短的未被标记的点;

    用这个点的边松弛;

    如此循环n-1次。

    虽然Dijkstra大部分时候不如SPFA快,但理论是Dijkstra更稳定。

    代码实现

    769ms的SPFA:

     1 #include<cstdio>
     2 int n,m,s,v[10010];
     3 int a,b,c;
     4 int q[500010],head,tail;
     5 int h[10010],hs;
     6 struct edge{int s,n,v;}e[500010];
     7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; }
     8 int main(){
     9     scanf("%d%d%d",&n,&m,&s);
    10     for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;
    11     for(int i=1;i<=m;i++){
    12         scanf("%d%d%d",&a,&b,&c);
    13         e[++hs]=(edge){b,h[a],c};
    14         h[a]=hs;
    15     }
    16     q[head++]=s;
    17     while(head>tail){
    18         a=q[tail++];
    19         for(int i=h[a];i;i=e[i].n){
    20             if(rel(v[e[i].s],v[a],e[i].v)){
    21                 q[head++]=e[i].s;
    22                 v[e[i].s]=v[a]+e[i].v;
    23             }
    24         }
    25     }
    26     for(int i=1;i<=n;i++) printf("%d ",v[i]);
    27     return 0;
    28 }
     1 #include<queue> 
     2 #include<cstdio>
     3 using namespace std;
     4 int n,m,s,v[10010];
     5 int a,b,c;
     6 priority_queue <int> q;
     7 int h[10010],hs;
     8 struct edge{int s,n,v;}e[500010];
     9 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; }
    10 int main(){
    11     scanf("%d%d%d",&n,&m,&s);
    12     for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;
    13     for(int i=1;i<=m;i++){
    14         scanf("%d%d%d",&a,&b,&c);
    15         e[++hs]=(edge){b,h[a],c};
    16         h[a]=hs;
    17     }
    18     q.push(s);
    19     while(!q.empty()){
    20         a=q.top();
    21         q.pop();
    22         for(int i=h[a];i;i=e[i].n){
    23             if(rel(v[e[i].s],v[a],e[i].v)){
    24                 q.push(e[i].s);
    25                 v[e[i].s]=v[a]+e[i].v;
    26             }
    27         }
    28     }
    29     for(int i=1;i<=n;i++) printf("%d ",v[i]);
    30     return 0;
    31 }
    2183ms优先队列(STL)优化的SPFA

    2305ms的Dijkstra:

     1 #include<cstdio>
     2 int n,m,s,w[10010];
     3 int a,b,c;
     4 bool v[10010];
     5 int h[10010],hs;
     6 struct edge{int s,n,v;}e[500010];
     7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0;}
     8 int main(){
     9     scanf("%d%d%d",&n,&m,&s);
    10     for(int i=1;i<=n;i++) if(i!=s) w[i]=2147483647;
    11     for(int i=1;i<=m;i++){
    12         scanf("%d%d%d",&a,&b,&c);
    13         e[++hs]=(edge){b,h[a],c};
    14         h[a]=hs;
    15     }
    16     v[s]=1;
    17     for(int i=h[s];i;i=e[i].n) if(rel(w[e[i].s],0,e[i].v)) w[e[i].s]=e[i].v;
    18     for(int k=1;k<n;k++){
    19         a=2147483647;
    20         for(int i=1;i<=n;i++) if(!v[i]&&w[i]<a) a=w[i],b=i;
    21         v[b]=1;
    22         for(int i=h[b];i;i=e[i].n) if(rel(w[e[i].s],w[b],e[i].v)) w[e[i].s]=e[i].v+w[b];
    23     }
    24     for(int i=1;i<=n;i++) printf("%d ",w[i]);
    25     return 0;
    26 }

    20分的堆优化的Dijkstra(恕我无能):

     1 #include<cstdio>
     2 #define LL long long
     3 #define maxn 10010
     4 #define maxm 500010
     5 #define inf 2147483647
     6 int n,m,q,w[maxn],in[maxn];
     7 int a,b,c,l,r;
     8 int p[maxn],ps,top;
     9 bool v[maxn];
    10 struct edge{int s,n,v;}e[maxm];
    11 struct heap{int s,v;}h[maxm];
    12 inline void add(int x,int y,int z){e[++ps]=(edge){y,p[x],z},p[x]=ps;}
    13 inline LL min(LL x,LL y,LL z){return x<y+z?x:y+z;}
    14 void swap(int x,int y,int xx,int yy){
    15     h[0]=(heap){h[x].s,h[x].v};
    16     h[x]=(heap){h[y].s,h[y].v};
    17     h[y]=(heap){h[0].s,h[0].v};
    18     in[xx]=y;in[yy]=x;
    19 }
    20 void push(int x,int y,int z){
    21     h[z]=(heap){x,y},in[x]=z;
    22     while(in[x]>1){
    23         if(h[in[x]].v<h[in[x]>>1].v) swap(in[x],in[x]>>1,x,h[in[x]>>1].s);
    24         else break;
    25     }
    26 }
    27 int pop(){
    28     int ret=h[1].s;
    29     h[1]=(heap){h[top].s,h[top--].v};
    30     int x=h[1].s,z;
    31     in[h[1].s]=1;
    32     while(in[x]<=top){
    33         l=in[x]<<1,r=l+1;
    34         if(h[l].v<h[r].v) z=l;
    35         else z=r;
    36         if(h[z].v<h[in[x]].v) swap(in[x],z,x,h[z].s);
    37         else break;
    38     }
    39     return ret;
    40 }
    41 int main(){
    42     scanf("%d%d%d",&n,&m,&q);
    43     for(int i=1;i<=n;i++) if(i!=q) w[i]=inf;
    44     for(int i=1;i<=m;i++){
    45         scanf("%d%d%d",&a,&b,&c);
    46         add(a,b,c);
    47     }
    48     for(int k=0;k<n;k++){
    49         if(k) q=pop();
    50         v[q]=1;
    51         for(int i=p[q];i;i=e[i].n){
    52             a=e[i].s,b=min(w[a],w[q],e[i].v);
    53             if(b<w[a]){
    54                 w[a]=b;
    55                 if(in[a]) push(a,w[a],in[a]);
    56                 else push(a,w[a],++top);
    57             }
    58         }
    59     }
    60     for(int i=1;i<=n;i++) printf("%d ",w[i]);
    61     return 0;
    62 }

    感觉洛谷的板子题都好厉害。

    题目来源:洛谷

  • 相关阅读:
    php7 安装mssql 扩展
    CentOS 7使用yum安装MYSQL
    PLSQL Developer 连接Linux 下Oracle的安装与配置
    VNC 在ubuntu desktop下只显示空白桌面
    Spring Boot 学习系列(11)—tomcat参数配置建
    Spring Boot 学习系列(10)—SpringBoot+JSP的使
    Spring Boot 学习系列(09)—自定义Bean的顺序加载
    Spring Boot 学习系列(08)—自定义servlet、filter及listener
    Spring Boot 学习系列(07)—properties文件读取
    Spring Boot 学习系列(06)—采用log4j2记录日志
  • 原文地址:https://www.cnblogs.com/J-william/p/6417146.html
Copyright © 2011-2022 走看看