华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2496|回复: 1
打印 上一主题 下一主题

P3371 【模板】单源最短路径

[复制链接]

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
跳转到指定楼层
楼主
发表于 2018-5-4 10:04:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P3371
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式
输入格式:
第一行包含三个整数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
回复

使用道具 举报

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
沙发
 楼主| 发表于 2021-5-17 20:30:44 | 只看该作者
我用一个标准的dijkstra 来做这个题,大家看看
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int inf=2147483647;
  4. const int mm=500050;
  5. const int mn=10010;
  6. int n,m,s;
  7. int nxt[mm],ev[mm],ew[mm];
  8. int dist[mn],vist[mn],nbs[mn],p[mn],heap[mn];

  9. int getmin()
  10. {
  11.         int m,k,i;
  12.         m=inf;
  13.         k=0;  ///起点,无路可找的时候就返回0
  14.         ///for (i=1;i<=n;i++)  cout<<dist[i]<<' '; cout<<endl;
  15.         for (i=1; i<=n; i++)
  16.                 if (!vist[i])
  17.                         if (dist[i]<m)
  18.                                 {
  19.                                         m=dist[i];
  20.                                         k=i;
  21.                                 }
  22.         return k;
  23. }

  24. void dijkstra(int src)
  25. {
  26.         int i,j,u,v,cnt=1;
  27.         for(i=1; i<=n; i++)
  28.                 {
  29.                         dist[i]=inf;
  30.                         vist[i]=0;
  31.                 };
  32.         dist[src]=0;
  33.         heap[1]=src;
  34.         while(cnt<=n)
  35.                 {
  36.                         u=getmin();
  37.                         cnt++;
  38.                         vist[u]=1;
  39.                         for(j=nbs[u]; j!=0; j=nxt[j])
  40.                                 {
  41.                                         v=ev[j];
  42.                                         if(!vist[v]&&dist[u]+ew[j]<dist[v])
  43.                                                 {
  44.                                                         dist[v]=dist[u]+ew[j];
  45.                                                         p[v]=u;
  46.                                                 }
  47.                                 }
  48.                 }
  49. }
  50. void printpath(int i)///反推路径找到S到I的路
  51. {
  52.         int path[mn]= {i,}; ///初始终点
  53.         int j=0,k=i;
  54.         while (p[k]!=0)  ///完全类似导弹飞机的倒推
  55.                 {
  56.                         j++;
  57.                         path[j]=p[k];
  58.                         k=p[k];
  59.                 }
  60.         cout<<s<<"-->"<<i<<':';
  61.         for (; j>=0; j--) cout<<path[j];
  62.         cout<<endl;
  63. }
  64. int main()
  65. {
  66.         int i,u,v,w;
  67.         scanf("%d%d%d",&n,&m,&s);
  68.         for(i=1; i<=n; i++)nbs[i]=0;
  69.         for(i=1; i<=m; i++)
  70.                 {
  71.                         scanf("%d%d%d",&u,&v,&w);
  72.                         nxt[i]=nbs[u];
  73.                         nbs[u]=i;
  74.                         ev[i]=v;
  75.                         ew[i]=w;///这里考虑一下如何去掉重复的边,
  76.                 }
  77.         dijkstra(s);
  78.         for (i=1; i<=n; i++)  printf("%d ",dist[i]);
  79.         ///cout<<endl;
  80.         ///for (i=1; i<=n; i++)  printpath(i);
  81.         return 0;
  82. }
复制代码


注意此题数据规模比较大,读入输出要用scanf和printf,否则只有70分
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-12-25 14:33 , Processed in 0.409080 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表