有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数NN、MM、SS、DD,其中NN(2le Nle 5002≤N≤500)是城市的个数,顺便假设城市的编号为0~(N-1N−1);MM是高速公路的条数;SS是出发地的城市编号;DD是目的地的城市编号。随后的MM行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
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
/************************************************************************************************************/
本程序是对dijkstra算法的应用,由于在题目中显示的是有两个权重的表示,首先必须要保证有最短的路径,在查看图中是否有多条具有相同最短路径,在其中选择最低的消费。
本程序采用邻接链表的形式,当在有多条相同路径中,只在图中标记起始点的邻接边中的顶点。
1 /*由于在这其中的过程中涉及到dijkstra,并且出现两条相等的路径的算法,如果*/ 2 /*在运算的过程中采用邻接链表的方式用dijkstra*/ 3 4 #include<iostream> 5 #include<malloc.h> 6 using namespace std; 7 8 #define INF (100000) 9 #define MAX 100 10 //如果采用邻接链表的形式构造图,在每一个顶点中接下存储的边是其相邻的边 11 typedef struct _Edge{ 12 int Adjv; 13 int Weight; 14 int costValue; 15 16 _Edge *Next; 17 }Edge,nedge; 18 19 typedef struct _VNode 20 { 21 int NodeName; 22 bool flag; 23 nedge *first_edge; 24 }VNode; 25 26 typedef struct _Graph{ 27 int Vernum; 28 int Edgnum; 29 VNode G[MAX]; 30 31 }MGraph; 32 33 MGraph *Graph; 34 35 void link_last(nedge *list, nedge *node) 36 { nedge *p=list; 37 while(p->Next!=NULL) 38 { 39 p=p->Next; 40 } 41 p->Next=node; 42 node->Next=NULL; 43 } 44 45 MGraph *BuildMyGraph(int N,int M) 46 { MGraph *pG; 47 pG=(MGraph*)malloc(sizeof( _Graph)); 48 49 pG->Vernum=N;pG->Edgnum=M; 50 51 //将点初始化 52 for(int i=0;i<N;i++) 53 { 54 pG->G[i].NodeName=i; 55 pG->G[i].flag=false; 56 pG->G[i].first_edge=NULL; 57 } 58 //输入数据 59 int c1,c2,w1,cost1,i,j; 60 Edge *edge; 61 for(i=0;i<pG->Edgnum;i++) 62 { 63 cin>>c1>>c2>>w1>>cost1; 64 edge=(Edge*)malloc(sizeof(_Edge)); 65 edge->Adjv=c2;edge->Weight=w1;edge->costValue=cost1;edge->Next=NULL; 66 for(j=0;j<pG->Vernum;j++) 67 { 68 if(c1==pG->G[j].NodeName) 69 { 70 if(pG->G[j].first_edge==NULL) 71 { 72 pG->G[j].first_edge=edge; 73 } 74 else 75 { 76 link_last(pG->G[j].first_edge,edge); 77 } 78 } 79 } 80 } 81 return pG; 82 } 83 int get_weight(int b,int a) 84 { 85 Edge *egd=Graph->G[b].first_edge; 86 int min=INF; 87 if(b==a) 88 { 89 return 0; 90 } 91 while(egd!=NULL) 92 { 93 if(a==egd->Adjv) 94 { 95 if(egd->Weight<min) 96 { 97 min=egd->Weight; 98 } 99 } 100 egd=egd->Next; 101 } 102 return min; 103 } 104 105 int Path(int prev[],int v,int e ) 106 { int cost=0; Edge *item; 107 //输出最短路径同时Graph标记号已经走过的点 108 int i=0,j=0; int rev[MAX]; 109 110 for(i=e ;i!=v ; i=prev[i]) 111 { 112 rev[j++]=i; 113 if(prev[i]==v) 114 Graph->G[i].flag=true;//只把与起始点相邻的定点进行标记 115 } 116 rev[j]=v; 117 for(j;j>0;j--) 118 { int t=j-1; 119 item=Graph->G[rev[j]].first_edge; 120 { 121 while(item!=NULL) 122 { 123 if(rev[t]==item->Adjv) 124 { cost=cost+item->costValue; 125 break; 126 } 127 item=item->Next; 128 } 129 } 130 } 131 132 return cost; 133 } 134 135 int dijkstra(int begin,int end,int *path) 136 {//保证循环过程中begin和end所在点不能被标记 137 int prev[MAX],dist[MAX],flag[MAX]; int path_cost; 138 139 int i ,j ,k=begin; 140 141 for(i=0;i<Graph->Vernum;i++) 142 { 143 flag[i]=0; 144 prev[i]=-1; 145 dist[i]=get_weight(begin ,i); 146 147 } 148 149 for(i=0;i<Graph->Vernum;i++) 150 { 151 if(dist[i]!=INF) 152 { 153 prev[i]=0; 154 } 155 } 156 157 flag[begin]=1; 158 dist[begin]=0; 159 int min,tmp; 160 //开始进行dijkstra计算 161 for(i=1;i<Graph->Vernum;i++) 162 { 163 min=INF; 164 for(j=0;j<(*Graph).Vernum;j++) 165 { 166 if(Graph->G[j].first_edge!=NULL) 167 { 168 if(dist[j]<min && !flag[j] && Graph->G[j].flag==false) 169 { 170 min=dist[j]; 171 k=j; 172 } 173 } 174 } 175 flag[k]=1; 176 //更新prev和dist矩阵 177 for(j=0;j<Graph->Vernum;j++) 178 { 179 tmp=get_weight(k,j); 180 tmp = (tmp==INF ? INF : (min + tmp)); 181 if(!flag[j] && (tmp<dist[j]) && Graph->G[j].flag==false) 182 { 183 dist[j]=tmp; 184 prev[j]=k; 185 } 186 } 187 } 188 189 //dijkstra把起始点到各个顶点的最短路径,但是我们只需要从起始点到终点的路径就行了 190 if(dist[end]!=INF) 191 { 192 *path=dist[end]; 193 path_cost= Path( prev,begin,end ); 194 } 195 else
{
return -1;
}
196 return path_cost; 197 } 198 int main() 199 { 200 201 int N,M,W,D; 202 cin>>N>>M>>W>>D; 203 204 Graph=BuildMyGraph(N,M); 205 206 int cout=0; 207 for(int i=0;i<Graph->Vernum;i++) 208 { 209 if(W==Graph->G[i].NodeName) 210 { Edge *item=Graph->G[i].first_edge; 211 while(item!=NULL) 212 { 213 cout++; 214 item=item->Next; 215 } 216 } 217 } 218 219 int path_cost=0,temp=INF; 220 int path=0,temp_path=INF; 221 //接下来对图进行dijkstra算法研究 222 for(int j=0;j<cout;j++) 223 { 224 path_cost=dijkstra(W,D,&path); 225 if(path_cost==-1)
{
printf("没有最短路径 ");
exit(0);
}
226 Graph->G[D].flag=false; 227 if(temp_path>=path) 228 { 229 temp_path=path; 230 if(temp>=path_cost) 231 { 232 temp=path_cost; 233 } 234 } 235 else 236 { 237 printf("%d %d",D,temp); 238 return 0; 239 break; 240 } 241 242 } 243 return 0; 244 }
同时结果的显示: