数据结构实验之图论七:驴友计划 oj

本文介绍了一道经典的图论问题——寻找从起点到终点的最短路径,并且当有多条最短路径时选择过路费最少的一条。提供了五种不同的算法实现,包括Floyd算法、Dijkstra算法、SPFA算法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构实验之图论七:驴友计划

Time Limit: 1000MS Memory limit: 65536K

dalao代码,保存一下

题目描述

做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。

输入

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。 

输出

在同一行中输出路径长度和收费总额,数据间用空格间隔。 

示例输入

1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

示例输出

3 40

提示

 

来源

xam 

示例程序

 解法一:(Floyd算法)
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #define Max 100000000  
  5. int main()  
  6. {  
  7.     int n,m,i,j,k,x,y,t,p,s,e,l;  
  8.     int code[510][510],dis[510][510];  
  9.     scanf("%d",&l);  
  10.     while(l--)  
  11.     {  
  12.         scanf("%d %d %d %d",&n,&m,&s,&e);  
  13.         for(i=0;i<=n;i++)  
  14.             for(j=0;j<=n;j++)  
  15.             if(i==j)  
  16.             {  
  17.                 code[i][j]=0;  
  18.                 dis[i][j]=0;  
  19.             }  
  20.         else  
  21.             {  
  22.                 code[i][j]=Max;  
  23.                 dis[i][j]=Max;  
  24.             }  
  25.         for(i=1;i<=m;i++)  
  26.         {  
  27.             scanf("%d %d %d %d",&x,&y,&t,&p);  
  28.             if(code[x][y]>t)  
  29.             {  
  30.                 code[x][y]=t;  
  31.                 code[y][x]=t;  
  32.                 dis[x][y]=p;  
  33.                 dis[y][x]=p;  
  34.             }  
  35.         }  
  36.         for(i=s;i<=e;i++)  
  37.         {  
  38.             for(j=s;j<=e;j++)  
  39.             {  
  40.                 for(k=s;k<=e;k++)  
  41.                 {  
  42.                     if(code[j][k]>(code[i][j]+code[i][k])||(code[j][k]==(code[i][j]+code[i][k])&&dis[j][k]>(dis[i][j]+dis[i][k])))  
  43.                        {  
  44.                         code[j][k]=code[i][j]+code[i][k];  
  45.                         dis[j][k]=dis[i][j]+dis[i][k];  
  46.   
  47.                        }  
  48.                 }  
  49.             }  
  50.         }  
  51.         printf("%d %d\n",code[s][e],dis[s][e]);  
  52.     }  
  53.     return 0;  
  54. }  


解法二:(Dijkstra算法)

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #define INF 65535  
  4. struct node  
  5. {  
  6.     int a,b;  
  7. } map[1005][1005];;  
  8. int p[10010],final[1010],d[1000],d1[1010],s;  
  9. int n,m;  
  10. void Dijkstra()  
  11. {  
  12.     int v,w,k,min,mi;  
  13.     for(v=1;v<=n;v++)  
  14.     {  
  15.         final[v]=0;  
  16.         d[v]=map[s][v].a;  
  17.         d1[v]=map[s][v].b;  
  18.         p[v]=0;  
  19.     }  
  20.     d[s]=0;  
  21.     d1[s]=0;  
  22.     final[s]=1;  
  23.     for(v=2;v<=n;v++)  
  24.     {  
  25.         min=INF;  
  26.         mi=INF;  
  27.         for(w=1;w<=n;w++)  
  28.         {  
  29.             if(!final[w]&&(d[w]<min)||(d[w]==min&&mi>d1[w]))  
  30.             {  
  31.                 k=w;  
  32.                 min=d[w];  
  33.                 mi=d1[w];  
  34.             }  
  35.         }  
  36.         final[k]=1;  
  37.         for(w=1;w<=n;w++)  
  38.         {  
  39.             if(!final[w]&&(min+map[k][w].a<d[w]||(min+map[k][w].a==d[w]&&mi+map[k][w].b<d1[w])))  
  40.             {  
  41.                 d[w]=min+map[k][w].a;  
  42.                 d1[w]=mi+map[k][w].b;  
  43.                 p[w]=k;  
  44.             }  
  45.         }  
  46.     }  
  47. }  
  48. int main()  
  49. {  
  50.     int i,j,k,l1,l2,l3,l4,x,t;  
  51.     scanf("%d",&t);  
  52.     while(t--)  
  53.     {  
  54.         scanf("%d %d %d %d",&n,&m,&s,&x);  
  55.         for(i=0;i<=n;i++)  
  56.             for(j=0;j<=n;j++)  
  57.             if(i==j)  
  58.             {  
  59.                 map[i][j].a=0;  
  60.                 map[i][j].b=0;  
  61.             }  
  62.         else  
  63.             {  
  64.                 map[i][j].a=INF;  
  65.                 map[i][j].b=INF;  
  66.             }  
  67.         for(i=0;i<m;i++)  
  68.         {  
  69.             scanf("%d %d %d %d",&l1,&l2,&l3,&l4);  
  70.             map[l1][l2].a=l3;  
  71.             map[l2][l1].a=l3;  
  72.             map[l1][l2].b=l4;  
  73.             map[l2][l1].b=l4;  
  74.         }  
  75.         Dijkstra();  
  76.             printf("%d %d\n",d[x],d1[x]);  
  77.     }  
  78. }  



解法三:(SPFA算法_bfs)

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<queue>  
  4. #include<climits>  
  5. using namespace std;  
  6. long long INF=LONG_LONG_MAX;  
  7. long long dis[600],dis1[600];  
  8. int vis[600];  
  9. struct node  
  10. {  
  11.     int to;  
  12.     int w,w1;  
  13. };  
  14. int n,m,s,t,x;  
  15. vector<struct node>map[600];  
  16. void SPFA()  
  17. {  
  18.     queue<int>a;  
  19.     for(int i=0;i<n;i++)  
  20.     {  
  21.                 dis[i]=INF;  
  22.                 dis1[i]=INF;  
  23.     }  
  24.     memset(vis,0,sizeof(vis));  
  25.     dis[s]=0;  
  26.     dis1[s]=0;  
  27.     vis[s]=1;  
  28.     a.push(s);  
  29.     while(!a.empty())  
  30.     {  
  31.         int u=a.front();  
  32.         a.pop();  
  33.         vis[u]=0;  
  34.         int tt=map[u].size();  
  35.         for(int i=0;i<tt;i++)  
  36.         {  
  37.             int to=map[u][i].to;  
  38.   
  39.                 if(dis[u]<INF&&(dis[to]>dis[u]+map[u][i].w||(dis[to]==dis[u]+map[u][i].w)&&dis1[to]>dis1[u]+map[u][i].w))  
  40.                 {  
  41.                     dis[to]=dis[u]+map[u][i].w;  
  42.                     dis1[to]=dis1[u]+map[u][i].w1;  
  43.                     if(!vis[to])  
  44.                     {  
  45.                         a.push(to);  
  46.                         vis[to]=1;  
  47.                     }  
  48.             }  
  49.         }  
  50.     }  
  51. }  
  52. int main()  
  53. {  
  54.     int T,u,v,w,w1;  
  55.     struct node temp;  
  56.     scanf("%d",&T);  
  57.     while(T--)  
  58.     {  
  59.         scanf("%d %d %d %d",&n,&m,&s,&t);  
  60.         for(int i=0;i<n;i++)  
  61.             map[i].clear();  
  62.         for(int i=1;i<=m;i++)  
  63.         {  
  64.             scanf("%d %d %d %d",&u,&v,&w,&w1);  
  65.             temp.to=v;  
  66.             temp.w=w;  
  67.             temp.w1=w1;  
  68.             map[u].push_back(temp);  
  69.             temp.to=u;  
  70.             map[v].push_back(temp);  
  71.         }  
  72.             SPFA();  
  73.                 printf("%lld %lld\n",dis[t],dis1[t]);  
  74.     }  
  75. }  


解法四:(SPFA_dfs算法)

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. int INF=65535;  
  4. int d[600],d1[600];  
  5. int vis[600],head[600];  
  6. struct node  
  7. {  
  8.     int v;  
  9.     int w,w1;  
  10.     int next;  
  11. }st[100000];  
  12. int n,m,s,t,x,l;  
  13. void add(int u,int v,int w,int w1)  
  14. {  
  15.     st[l].v=v;  
  16.     st[l].w=w;  
  17.     st[l].w1=w1;  
  18.     st[l].next=head[u];  
  19.     head[u]=l++;  
  20. }  
  21. int spfa_dfs(int u)  
  22. {  
  23.     vis[u]=1;  
  24.     for(int k=head[u]; k!=-1; k=st[k].next)  
  25.     {  
  26.         int v=st[k].v,w=st[k].w,w1=st[k].w1;  
  27.         if( d[u]+w <d[v]||(d[u]+w ==d[v]&&d1[u]+w1 <d1[v] ))  
  28.         {  
  29.             d[v]=d[u]+w;  
  30.             d1[v]=d1[u]+w1;  
  31.             if(!vis[v])  
  32.             {  
  33.                 if(spfa_dfs(v))  
  34.                     return 1;  
  35.             }  
  36.             else  
  37.                 return 1;  
  38.         }  
  39.     }  
  40.     vis[u]=0;  
  41.     return 0;  
  42. }  
  43. int main()  
  44. {  
  45.     int T,u,v,w,w1,k,i;  
  46.     scanf("%d",&T);  
  47.     while(T--)  
  48.     {  
  49.         l=0;  
  50.         scanf("%d %d %d %d",&n,&m,&s,&t);  
  51.         for(i=0;i<=n;i++)  
  52.         {  
  53.             d[i]=INF;  
  54.             d1[i]=INF;  
  55.         }  
  56.         memset(head,-1,sizeof(head));  
  57.         for(int i=1;i<=m;i++)  
  58.         {  
  59.             scanf("%d %d %d %d",&u,&v,&w,&w1);  
  60.             add(u,v,w,w1);  
  61.             add(v,u,w,w1);  
  62.         }  
  63.         d[s]=0;  
  64.         d1[s]=0;  
  65.         k=spfa_dfs(s);  
  66.                 printf("%d %d\n",d[t],d1[t]);  
  67.     }  
  68. }  


解法五:(Bellman_Ford)

  1. #include<stdio.h>  
  2. #include<iostream>  
  3. #include<string.h>  
  4. using namespace std;  
  5. #define INF 0x7ffffff  
  6. struct node  
  7. {  
  8.     int to,cost,cost1;  
  9. }edge[2000];  
  10. int pre[600];  
  11. int dis[600],dis1[600];  
  12. int n,m,src;  
  13. int relax(int u,int v,int cost,int cost1)  
  14. {  
  15.     if(dis[v]>dis[u]+cost||(dis[v]==dis[u]+cost&&dis1[v]>dis1[u]+cost1))  
  16.     {  
  17.         dis[v]=dis[u]+cost;  
  18.         dis1[v]=dis1[u]+cost1;  
  19.         return 1;  
  20.     }  
  21.     else  
  22.         return 0;  
  23. }  
  24. int Bellman_Ford()  
  25. {  
  26.     int i,j,flag;  
  27.     for(i=1;i<=n;i++)  
  28.         {  
  29.             dis[i]=INF;  
  30.             dis1[i]=INF;  
  31.         }  
  32.         dis[i]=0;  
  33.             dis1[i]=0;  
  34.     for(i=1;i<n;i++)  
  35.         {  
  36.             flag=0;  
  37.             for(j=0;j<m;j++)  
  38.             {  
  39.                 if(relax(j,edge[j].to,edge[j].cost,edge[j].cost1))  
  40.                 {  
  41.                     pre[j]=edge[j].to;  
  42.                     flag=1;  
  43.                 }  
  44.             }  
  45.             if(!flag)  
  46.                 break;  
  47.         }  
  48.         for(i=0;i<m;i++)  
  49.         {  
  50.             if(relax(i,edge[i].to,edge[i].cost,edge[i].cost1))  
  51.                 return 0;  
  52.         }  
  53.         return 1;  
  54. }  
  55. int main()  
  56. {  
  57.     int i,j,T,t,l1,l2,l3,l4;  
  58.     scanf("%d",&T);  
  59.     while(T--)  
  60.     {  
  61.         scanf("%d %d %d %d",&n,&m,&src,&t);  
  62.         for(i=0;i<m;i++)  
  63.         {  
  64.             scanf("%d %d %d %d",&l1,&l2,&l3,&l4);  
  65.             edge[l1].to=l2;  
  66.             edge[l1].cost=l3;  
  67.             edge[l1].cost1=l4;  
  68.             edge[l2].to=l1;  
  69.             edge[l2].cost=l3;  
  70.             edge[l2].cost1=l4;  
  71.   
  72.         }  
  73.         Bellman_Ford();  
  74.         //if(Bellman_Ford())  
  75.             printf("%d %d\n",dis[t],dis1[t]);  
  76.     }  
  77. }  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值