数据结构 全国省会城市交通咨询

设计一个交通咨询系统,通过读取全国城市距离图(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;
}

猜你喜欢

转载自blog.csdn.net/qq_35850147/article/details/106159693