bfs输出路径 && 最短路(迪杰斯特拉)输出路径
问题描述
解决方法
1、像第一个问题那就是最短路问题(我代码采用迪杰斯特拉算法)实现
2、换乘次数最少,那就用bfs广搜来寻找答案。但是我的代码不能保证这个最少换乘是最短路程
代码
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int maxn=1e3; 9 const int INF=0x3f3f3f3f; 10 int on[maxn],v[maxn]; 11 //on数组是用来记录路径的 12 //v数组是用来记录最短路径长度的 13 struct shudui 14 { 15 int x,step; 16 }; 17 struct shudui2 18 { 19 int x,value; 20 }; 21 struct shudui1 22 { 23 int start,value; 24 bool operator < (const shudui1 q)const //这个是用于优先队列,最短路算法采用”迪杰斯特拉+堆优化“ 25 { 26 return value<q.value; 27 } 28 }; 29 vector<shudui2>w[maxn]; //定义一个shudui2类型的vector容器 30 void bfs(int st,int en) //这个是用bfs找到最少换乘次数 31 { 32 //st代表起点,en代表终点 33 int ans=INF; 34 shudui str1,str2; 35 system("cls"); 36 int flag=0; 37 memset(on,0,sizeof(on)); 38 queue<shudui>r; 39 //为bfs搜索创建一个队列 40 str1.x=st; 41 str1.step=0; 42 r.push(str1); 43 while(!r.empty()) 44 { 45 str1=r.front();//从队列头取元素 46 r.pop(); 47 int x=str1.x; 48 for(int i=0; i<w[x].size(); ++i) //遍历x这个点能到达的所有点,把它们都加入到队列中 49 { 50 str2.x=w[x][i].x; 51 on[str2.x]=str1.x; //记录路径 52 if(w[x][i].x==en) //这就代表找到了最短路径 53 { 54 int index=en; 55 flag=1; 56 printf("最短换乘%d次\n",str1.step); 57 printf("以下是路径\n"); 58 printf("%d",index); 59 while(on[index]>0) //循环打印路径 60 { 61 index=on[index]; 62 printf("--->%d",index); 63 if(index==st) break; 64 } 65 printf("\n"); 66 break; 67 } 68 69 str2.step=str1.step+1; //每换乘一次要加1 70 r.push(str2); 71 } 72 if(flag) break; 73 } 74 while(!r.empty()) r.pop(); 75 if(!flag) 76 { 77 printf("没有通向此处航线\n"); 78 } 79 } 80 void JK(int s,int e) //迪杰斯特拉算法求最短路 81 { 82 //s是起点,e是终点 83 system("cls"); 84 memset(on,0,sizeof(on)); 85 memset(v,INF,sizeof(v)); 86 priority_queue<shudui1>r; 87 shudui2 str2; 88 shudui1 str1; 89 v[s]=0; 90 str1.start=s; 91 str1.value=0; 92 r.push(str1); //把起点放入优先队列 93 while(!r.empty()) 94 { 95 int x,y; 96 str1=r.top(); //从优先队列头拿出元素 97 r.pop(); 98 x=str1.start; 99 y=str1.value; 100 if(v[x]<y) continue; 101 //说明在这个点再此之后又入队了 102 //此次出队的并不是s到这个点的最短路, 103 //所以在这次更新前点v所连的点已经更过一次了 104 //所以后面也不会进行松弛操作 105 int len=w[x].size(); 106 for(int i=0; i<len; ++i) // 107 { 108 str2=w[x][i]; 109 if((v[x]+str2.value<v[str2.x])) //遍历x这个点能到达的所有点,把它们都加入到队列中 110 { 111 on[str2.x]=x; //记录路径 112 v[str2.x]=v[x]+str2.value; 113 str1.start=str2.x; 114 str1.value=v[str2.x]; 115 r.push(str1); 116 } 117 } 118 } 119 printf("最短路径长度为%d\n",v[e]); 120 printf("路径如下\n"); 121 printf("%d",e); 122 int x=e; 123 while(on[x]>0) //循环打印路径 124 { 125 x=on[x]; 126 printf("-->%d",x); 127 } 128 printf("\n"); 129 } 130 int main() 131 { 132 int n,m,x; 133 printf("输入有几个点,有几条边\n"); 134 scanf("%d%d",&n,&m); 135 printf("依次输入每条路线的起点、终点、距离\n"); 136 while(m--) 137 { 138 shudui2 str2; 139 int x,y,z; 140 scanf("%d%d%d",&x,&y,&z); 141 str2.x=y; 142 str2.value=z; 143 w[x].push_back(str2); //往vector容器里面添加元素 144 str2.x=x; 145 w[y].push_back(str2); 146 } 147 while(1) 148 { 149 int s,e; 150 system("cls"); 151 printf ( " \n"); 152 printf ( " \n"); 153 printf ( " \n"); 154 printf ("-------------------------------------- \n"); 155 printf ("--------------------------------------\n"); 156 printf ("--------丨[0]最短路程 丨---\n"); 157 printf ("--------丨[1]最少换乘 丨---\n"); 158 printf ("--------丨[2]结束 丨---\n"); 159 printf ("----------输入相应数字----------------\n"); 160 printf ("--------------------------------------- \n"); 161 printf ( " \n"); 162 printf ( " \n"); 163 scanf("%d",&x); //正常if判断语句 164 if(x==0) 165 { 166 printf("输入终点编号、起点编号\n"); 167 scanf("%d%d",&s,&e); 168 JK(s,e); 169 } 170 else if(x==1) 171 { 172 printf("输入终点编号、起点编号\n"); 173 scanf("%d%d",&s,&e); 174 bfs(s,e); 175 } 176 else if(x==2) 177 { 178 break; 179 } 180 else printf("输入格式不正确\n"); 181 system("pause"); 182 } 183 return 0; 184 } 185 /* 186 测试数据 187 5 5 188 1 2 20 189 2 3 30 190 3 4 20 191 4 5 20 192 1 5 100 193 */