设计一个交通咨询系统,通过读取全国城市距离图(http://pan.baidu.com/s/1jIauHSE,请在程序运行时动态加载到内存),实现:
1、请验证全国其他省会城市(不包括海口)到武汉中间不超过2个省(省会城市)是否成立?(正是因为武汉处于全国的中心位置,此次疫情才传播的如此广) ;
2、允许用户查询从任一个城市到另一个城市之间的最短路径(两种算法均要实现,界面上可自行选择)以及所有不重复的可行路径(可限制最多经过10个节点),并利用快速排序对所有路径方案依据总长度进行排序输出(输出到文件),每一条结果均需包含路径信息及总长度,试比较排序后的结果与迪杰斯特拉算法和费洛伊德算法输出的结果;
3、假设在求解2个城市间最短路径时需要绕过某个特定的城市(用户输入或者选择,例如武汉),请问应该如何实现?
adjacency.txt
北京 上海 天津 重庆 哈尔滨 长春 沈阳 呼和浩特 石家庄 太原 济南 郑州 西安 兰州 银川 西宁 乌鲁木齐 合肥 南京 杭州 长沙 南昌 武汉 成都 贵阳 福州 台北 广州 海口 南宁 昆明 拉萨 香港 澳门
北京 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
上海 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
天津 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
重庆 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0
哈尔滨 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
长春 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
沈阳 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
呼和浩特 0 0 0 0 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
石家庄 1 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
太原 0 0 0 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
济南 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
郑州 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
西安 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0
兰州 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
银川 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
西宁 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0
乌鲁木齐 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
合肥 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0
南京 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
杭州 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0
长沙 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 0 1 0 0 0 0
南昌 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 0 0 0
武汉 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0
成都 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0
贵阳 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 0 0
福州 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 0
台北 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
广州 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 0 0 1 1
海口 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0
南宁 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0
昆明 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0
拉萨 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
香港 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1
澳门 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1
distance.txt
北京 上海 天津 重庆 哈尔滨 长春 沈阳 呼和浩特 石家庄 太原 济南 郑州 西安 兰州 银川 西宁 乌鲁木齐 合肥 南京 杭州 长沙 南昌 武汉 成都 贵阳 福州 台北 广州 海口 南宁 昆明 拉萨 香港
北京
上海 1065
天津 104 963
重庆 1465 1445 1447
哈尔滨 1055 1675 1069 2515
长春 854 1444 856 2301 235
沈阳 621 1191 604 2040 509 275
呼和浩特 408 1374 495 1342 1321 1160 974
石家庄 270 991 267 1195 1323 1117 870 385
太原 406 1099 426 1081 1458 1261 1024 335 168
济南 366 729 280 1253 1295 1069 798 648 273 416
郑州 617 827 574 893 1637 1417 1151 689 366 356 361
西安 917 1223 916 572 1973 1769 1520 772 652 518 779 444
兰州 1187 1718 1226 768 2192 2020 1807 874 970 803 1182 906 503
银川 897 1595 951 979 1870 1706 1506 549 717 554 965 771 510 334
西宁 1333 1913 1381 906 2306 2146 1946 987 1134 967 1359 1097 699 196 441
乌鲁木齐 2417 3269 2504 2306 3062 2999 2905 2010 2335 2192 2605 2445 2114 1625 1674 1439
合肥 898 402 812 1061 1743 1508 1235 1112 734 796 533 468 827 1327 1234 1523 2906
南京 900 266 805 1207 1667 1432 1162 1161 776 864 538 567 957 1452 1338 1647 3012 146
杭州 1126 169 1028 1314 1816 1583 1322 1397 1012 1098 769 789 1148 1650 1559 1846 3231 326 236
长沙 1341 886 1279 647 2293 2061 1786 1409 1104 1077 1012 739 781 1229 1290 1412 2850 581 706 730
南昌 1248 611 1170 911 2121 1886 1613 1399 1048 1066 890 710 906 1395 1392 1587 3018 378 469 449 286
武汉 1050 684 983 762 1993 1761 1486 1157 825 823 713 469 653 1149 1133 1343 2767 312 454 558 301 260
成都 1521 1659 1521 266 2576 2373 2124 1326 1257 1118 1367 1010 605 601 877 699 2058 1263 1408 1540 906 1159 982
贵阳 1735 1527 1703 328 2769 2548 2279 1651 1466 1370 1481 1132 880 1088 1307 1211 2571 1183 1322 1376 647 932 871 519
福州 1559 611 1466 1312 2283 2051 1791 1778 1404 1455 1193 1107 1350 1841 1829 2032 3463 670 663 469 666 445 699 1571 1256
台北 1717 688 1620 1561 2347 2120 1874 1971 1589 1657 1358 1319 1590 2084 2059 2277 3704 861 819 592 915 691 937 1821 1492 250
广州 1889 1213 1819 977 2791 2556 2283 1971 1661 1640 1544 1298 1308 1699 1816 1863 3282 1048 1132 1045 562 670 839 1234 764 694 866
海口 2233 1630 2173 1073 3178 2944 2670 2262 1988 1942 1906 1623 1536 1840 2020 1977 3336 1439 1535 1462 895 1067 1193 1289 770 1105 1252 419
南宁 2050 1603 2002 770 3042 2812 2538 2029 1792 1723 1749 1432 1276 1536 1738 1663 3009 1339 1457 1436 760 998 1054 969 452 1168 1363 505 328
昆明 2086 1950 2067 621 3136 2921 2658 1944 1816 1699 1866 1507 1183 1232 1517 1298 2507 1602 1743 1798 1068 1353 1290 640 423 1652 1878 1074 914 607
拉萨 2563 2902 2597 1485 3558 3394 3183 2238 2336 2171 2518 2190 1747 1377 1689 1252 1603 2503 2647 2786 2128 2396 2228 1246 1560 2787 3032 2312 2178 1872 1266
香港 1969 1230 1895 1108 2843 2608 2336 2071 1750 1738 1617 1391 1426 1827 1935 1992 3413 1106 1176 1064 665 730 925 1366 893 669 808 132 444 602 1189 2435
澳门 1987 1276 1916 1075 2876 2641 2368 2077 1763 1745 1639 1401 1416 1805 1924 1967 3382 1135 1212 1109 668 757 939 1330 848 726 871 108 382 540 1132 2382 0
main.cpp
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> p;
const int inf = 0x3f3f3f3f;
const int maxn = 50;
const int maxm = 5e3;
bool init_done, floyd_done, vis[maxn], adj[maxn][maxn];
int ecnt, head[maxn], dis[maxn], pre[maxn], sta[maxn], g[maxn][maxn];
struct edge { int v, w, nxt; } e[maxm];
vector<vector<int>> res;
unordered_map<string, int> id;
string city[maxn];
ifstream in_adj("adjacency.txt");
ifstream in_dis("distance.txt");
ofstream out("output.txt");
void addEdge(int u, int v, int w)
{
e[ecnt].v = v;
e[ecnt].w = w;
e[ecnt].nxt = head[u];
head[u] = ecnt++;
}
void init()
{
if (init_done)
{
cout << "无需重复初始化" << endl << endl;
return;
}
memset(head, -1, sizeof(head));
memset(g, 0x3f, sizeof(g));
for (int i = 1; i <= 34; i++)
{
in_adj >> city[i];
id[city[i]] = i;
}
for (int i = 1; i <= 34; i++)
{
string city_now;
in_adj >> city_now;
int id_now = id[city_now];
for (int j = 1; j <= 34; j++)
{
in_adj >> adj[id_now][j];
adj[j][id_now] = adj[id_now][j];
}
}
string tmp;
for (int i = 1; i <= 33; i++) in_dis >> tmp;
for (int i = 1; i <= 34; i++)
{
string city_now;
in_dis >> city_now;
int id_now = id[city_now];
for (int j = 1; j <= i - 1; j++)
{
int w;
in_dis >> w;
if (!adj[id_now][j]) continue;
g[id_now][j] = g[j][id_now] = w;
addEdge(id_now, j, w);
addEdge(j, id_now, w);
}
}
cout << "初始化成功" << endl << endl;
init_done = true;
}
int bfs(int src, int des)
{
memset(vis, false, sizeof(vis));
queue<p> q;
vis[src] = true;
q.push(p(src, 0));
while (!q.empty())
{
int u = q.front().first, s = q.front().second;
if (u == des) return s - 1;
q.pop();
for (int i = head[u]; ~i; i = e[i].nxt)
{
int v = e[i].v;
if (!vis[v])
{
vis[v] = true;
q.push(p(v, s + 1));
}
}
}
return inf;
}
void print_wuhan()
{
for (int i = 1; i <= 34; i++)
if (city[i] != "武汉")
cout << city[i] << "到武汉至少中转 " << bfs(i, id["武汉"]) << " 次" << endl << endl;
}
void dfs(int now, int des, int step, int sum, vector<int> res_now)
{
if (step > 10) return;
vis[now] = true;
res_now.push_back(now);
if (now == des)
{
res_now.push_back(sum);
res.push_back(res_now);
return;
}
for (int i = head[now]; ~i; i = e[i].nxt)
{
int nxt = e[i].v;
if (vis[nxt]) continue;
dfs(nxt, des, step + 1, sum + e[i].w, res_now);
vis[nxt] = false;
}
}
bool cmp(const vector<int>& va, const vector<int>& vb)
{
return va[va.size() - 1] < vb[vb.size() - 1];
}
void getPath()
{
res.clear();
memset(vis, false, sizeof(vis));
cout << "请分别输入起点名称和终点名称: ";
string city_src, city_des;
cin >> city_src >> city_des;
if (id.find(city_src) == id.end() || id.find(city_des) == id.end())
{
cout << "地点不存在" << endl << endl;
return;
}
int id_src = id[city_src], id_des = id[city_des];
dfs(id_src, id_des, 0, 0, {});
sort(res.begin(), res.end(), cmp);
int cnt = 0;
for (auto vec : res)
{
out << "第 " << ++cnt << " 条路径" << endl;
for (int i = 0; i < vec.size() - 2; i++)
out << "从 " << city[vec[i]] << " 到 " << city[vec[i + 1]] << endl;
out << "总路程为 " << vec[vec.size() - 1] << endl << endl;
}
cout << "所有 10 步以内的路径已输出到文件" << endl << endl;
}
void dijkstra(bool flag)
{
memset(dis, 0x3f, sizeof(dis));
memset(vis, false, sizeof(vis));
cout << "请分别输入起点名称和终点名称: ";
string city_src, city_des;
cin >> city_src >> city_des;
if (id.find(city_src) == id.end() || id.find(city_des) == id.end())
{
cout << "地点不存在" << endl << endl;
return;
}
int id_site = 0;
if (flag)
{
cout << "请分别输入起点名称和终点名称: ";
string city_site;
cin >> city_site;
if (id.find(city_site) == id.end())
{
cout << "地点不存在" << endl << endl;
return;
}
id_site = id[city_site];
}
priority_queue<p, vector<p>, greater<p> > q;
int id_src = id[city_src], id_des = id[city_des];
q.push(p(dis[id_src] = 0, id_src));
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = head[u]; ~i; i = e[i].nxt)
{
int v = e[i].v, w = e[i].w;
if (v != id_site && dis[v] > dis[u] + w)
{
pre[v] = u;
dis[v] = dis[u] + w;
q.push(p(dis[v], v));
}
}
}
cout << endl << city_src << " 到 " << city_des << " 的最短路径如下: " << endl;
int top = 0;
for (int i = id_des; i != id_src; i = pre[i]) sta[top++] = i;
for (int i = top - 1, last = id_src; i >= 0; i--)
{
int u = last, v = sta[i];
cout << "从 " << city[u] << " 到 " << city[v] << endl;
last = v;
}
cout << "总路程为 " << dis[id_des] << endl << endl;
}
void floyd_single(int n)
{
if (!floyd_done)
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
floyd_done = true;
cout << "请分别输入起点名称和终点名称: ";
string city_src, city_des;
cin >> city_src >> city_des;
if (id.find(city_src) == id.end() || id.find(city_des) == id.end())
{
cout << "地点不存在" << endl << endl;
return;
}
int id_src = id[city_src], id_des = id[city_des];
cout << endl << city_src << " 到 " << city_des << " 的最短路径长为: " << g[id_src][id_des] << endl << endl;
}
void floyd_all(int n)
{
if (!floyd_done)
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
floyd_done = true;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
cout << city[i] << " 到 " << city[j] << " 的最短路径长为 " << g[i][j] << endl << endl;
cout << endl;
}
bool chooseFunc()
{
int ope;
cin >> ope;
switch (ope)
{
case 1: init(); break;
case 2: print_wuhan(); break;
case 3: getPath(); break;
case 4: dijkstra(false); break;
case 5: dijkstra(true); break;
case 6: floyd_single(34); break;
case 7: floyd_all(34); break;
case 8: return false;
default: cout << "指令无效,请重新输入" << endl;
}
return true;
}
void showMenu()
{
cout << "请输入您需要进行的操作标号" << endl;
cout << "---------------------" << endl << endl;
cout << "1\t初始化交通网络图" << endl << endl;
cout << "2\t获取各省会/直辖市/特区到武汉中转次数" << endl << endl;
cout << "3\t获取指定起点到终点的所有路径" << endl << endl;
cout << "4\t获取单源最短路径 (Dijkstra)" << endl << endl;
cout << "5\t获取绕开指定地点的单源最短路径 (Dijkstra)" << endl << endl;
cout << "6\t获取单源最短路径 (Floyd)" << endl << endl;
cout << "7\t获取多源最短路径" << endl << endl;
cout << "8\t退出程序" << endl << endl;
cout << "---------------------" << endl;
}
int main()
{
do showMenu();
while (chooseFunc());
return 0;
}