1、設計方案 node
複賽增長了一個條件,也正是這個條件提高了問題的難度。諸如BFS等最短路徑算法均不能求解通過指定頂點的最短路徑。雖然如此,可是能夠考慮將這個問題轉換爲求解最短路徑問題。 ios
首先計算s到d的最短路徑,若是包含了全部的中間節點,顯然這就是符合條件的最優解了。若是沒有找到最短路徑,說明不存在一條路徑。比較複雜的狀況是找到了最短路徑,可是沒有包含全部中間節點。 算法
若是隻有一箇中間節點m,能夠將路徑從中間節點處分爲兩段。分別求兩段的最短路徑,若是兩段最短路徑除了m外沒有公共節點,那麼合併這兩段路徑能夠獲得最優解。兩段有除了m外的其它公共點就先計算其中一段路徑的最短路徑,從圖上去掉這個路徑所包含的節點,而後再求第二段路徑,合併能夠獲得一條從s到d通過m的路徑。兩次計算能夠求得s到d通過m的最短路徑。 windows
若是包含多箇中間節點就更爲複雜了。這種狀況下,考慮計算通過其中一箇中間節點的路徑。若是不存在通過某個節點的路徑那麼就不存在解。若是某條路徑包含了全部節點,那麼這條路徑是一個解。求出來全部這樣的解,其中的最短路徑是最優解。若是不存在某條路徑包含了全部的中間節點,那麼能夠知道,從s到d通過每個中間點都存在一條路徑,在這種狀況下,能夠遍歷m1,m2,…,mn依次求解s->m1->…->d,s->m2->…->d等,最後求得知足條件的最短路徑,但這樣得到的路徑不能保證是最短路徑。 app
若是以上方法均不能求得結果,那麼只有祭出最強神器——深度優先搜索。深度優先搜索可以遍歷全部路徑,能夠得到符合要求的最短路徑。雖然可以求得最優解,可是時間複雜度較高,在邊數較少的狀況下能夠快速求得解。爲了能在10分鐘內獲得解,在計算的過程當中檢查是否超時。 函數
2、性能 性能
本程序中,bfs的時間複雜度是O(E+V),其中E是邊數,V是節點數,解決問題須要調用O(N²)次bfs(雖然最後採用dfs來保底,可是主要是以bfs來解決問題的),其中N爲中間點數目,總的運行時間是O((E+V)N²)。 測試
首先,使用示例數據進行測試。 spa
zte.exe /fin.txt /oout.txt /s20 /d32 /m"22,23" 命令行
示例問題解決時間小於1秒。
下面增長几個點,而且打亂點的順序。如
zte.exe /fin.txt /oout.txt /s8 /d46 /m"37,31,47,48,39,22,23,20,45,24,32"
這個問題有11箇中間節點,解決時間小於1秒,能夠獲得路徑「main: 8, 45, 37, 29, 20, 21, 22, 23, 24, 32, 31, 30, 39, 4, 48, 47, 46」。
而後,本人寫了個程序用於生成一個圖,圖的節點有5000個,邊數總計有12158條。
先在5000個節點上求解幾個點。如
zte.exe /ftest.txt /oout.txt /s1 /d5000 /m"2,3,4,5,6"
解決這個問題的時間小於1秒。計算獲得的路徑爲main: 1, 35, 25, 31, 5, 2, 41, 42, 6, 3, 46, 22, 4, 50, 92, 89, 135, 179, 201, 239, 287, 336, 376, 407, 428, 458, 503, 551, 599, 644, 682, 721, 764, 806, 830, 858, 892, 940, 989, 1024, 1068, 1110, 1156, 1205, 1228, 1274, 1318, 1343, 1381, 1426, 1474, 1518, 1540, 1583, 1620, 1653, 1679, 1723, 1767, 1816, 1855, 1902, 1949, 1981, 2023, 2072, 2114, 2130, 2174, 2214, 2260, 2305, 2354, 2403, 2429, 2462, 2505, 2548, 2590, 2616, 2664, 2699, 2744, 2774, 2807, 2855, 2894, 2932, 2957, 2998, 3041, 3087, 3128, 3165, 3214, 3243, 3289, 3322, 3368, 3417, 3466, 3494, 3540, 3586, 3634, 3659, 3699, 3744, 3793, 3840, 3881, 3893, 3941, 3989, 4034, 4069, 4104, 4132, 4178, 4225, 4258, 4303, 4330, 4359, 4408, 4447, 4496, 4537, 4573, 4616, 4662, 4706, 4747, 4772, 4806, 4855, 4892, 4918, 4954, 5000。
這條路徑有139個節點,下面去掉起始節點和目的節點,而後打亂路徑其它節點的順序,再求解問題,以下
zte.exe /ftest.txt /oout.txt /s1 /d5000 /m"4258,4303,4330,4359,4408,407,428,458,503,551,599,644,682,721,764,806,830,858,892,940,989,1024,1068,35,25,31,5,2,2174,2214,2260,2305,2354,2403,2429,2462,2505,2548,2590,41,42,6,3,46,22,4,50,92,2616,2664,2699,2744,2774,2807,2855,2894,2932,2957,2998,3041,3087,3128,3165,3214,3243,3289,3322,3368,3417,3466,3494,3540,3586,3634,3659,3699,3744,3793,3840,3881,3893,3941,3989,4034,4069,4104,4132,4178,4225,1110,1156,1205,1228,1274,1318,1343,1381,1426,1474,1518,1540,1583,1620,1653,1679,1723,1767,4447,4496,4537,4573,4616,4662,4706,4747,4772,4806,4855,4892,4918,4954,89,135,179,201,239,287,336,376,1816,1855,1902,1949,1981,2023,2072,2114,2130"
雖然沒有獲得最優解,可是這個問題5秒內能夠解決。獲得的路徑爲「main: 1, 35, 76, 106, 155, 179, 201, 239, 287, 336, 376, 407, 428, 458, 503, 551, 599, 644, 682, 721, 764, 806, 830, 858, 892, 940, 989, 1024, 1068, 1110, 1156, 1205, 1228, 1274, 1318, 1343, 1381, 1426, 1474, 1518, 1540, 1583, 1620, 1653, 1679, 1723, 1767, 1816, 1855, 1902, 1949, 1981, 2023, 2072, 2114, 2130, 2174, 2214, 2260, 2305, 2354, 2403, 2429, 2462, 2505, 2548, 2590, 2616, 2664, 2699, 2744, 2774, 2807, 2855, 2894, 2932, 2957, 2998, 3041, 3087, 3128, 3165, 3214, 3243, 3289, 3322, 3368, 3417, 3466, 3494, 3540, 3586, 3634, 3659, 3699, 3744, 3793, 3840, 3881, 3893, 3941, 3989, 4034, 4069, 4104, 4132, 4178, 4225, 4258, 4303, 4330, 4359, 4408, 4379, 4342, 4331, 4301, 4269, 4230, 4181, 4141, 4099, 4050, 4010, 3965, 3921, 3884, 3836, 3814, 3768, 3729, 3691, 3650, 3607, 3575, 3526, 3501, 3462, 3428, 3389, 3353, 3304, 3287, 3238, 3189, 3145, 3103, 3064, 3053, 3032, 2990, 2942, 2904, 2873, 2838, 2792, 2769, 2726, 2697, 2657, 2634, 2593, 2547, 2503, 2461, 2417, 2394, 2363, 2317, 2289, 2242, 2208, 2172, 2138, 2090, 2045, 2002, 1963, 1922, 1899, 1858, 1830, 1782, 1739, 1691, 1666, 1627, 1602, 1555, 1517, 1498, 1453, 1405, 1392, 1345, 1297, 1255, 1217, 1184, 1168, 1120, 1073, 1032, 986, 962, 927, 888, 839, 797, 755, 729, 688, 643, 628, 591, 550, 507, 485, 439, 401, 364, 316, 276, 236, 187, 149, 126, 102, 68, 25, 31, 5, 2, 41, 42, 6, 3, 46, 22, 4, 50, 92, 89, 135, 151, 197, 226, 271, 318, 360, 386, 434, 472, 493, 536, 576, 620, 658, 700, 706, 743, 785, 831, 867, 899, 944, 984, 1009, 1036, 1084, 1121, 1161, 1203, 1250, 1296, 1298, 1344, 1389, 1411, 1441, 1488, 1512, 1556, 1590, 1639, 1677, 1725, 1773, 1815, 1845, 1888, 1920, 1951, 1998, 2047, 2049, 2098, 2137, 2186, 2231, 2268, 2308, 2341, 2374, 2423, 2442, 2487, 2527, 2573, 2598, 2622, 2661, 2700, 2737, 2779, 2809, 2848, 2869, 2907, 2956, 2989, 3035, 3080, 3089, 3131, 3153, 3169, 3215, 3242, 3268, 3314, 3347, 3394, 3440, 3487, 3499, 3546, 3573, 3618, 3667, 3712, 3761, 3772, 3819, 3839, 3878, 3923, 3972, 4003, 4039, 4077, 4116, 4146, 4186, 4229, 4266, 4307, 4336, 4384, 4429, 4447, 4496, 4537, 4573, 4616, 4662, 4706, 4747, 4772, 4806, 4855, 4892, 4918, 4954, 5000」。
再把這個路徑打亂,繼續求解。
zte.exe /ftest.txt /s1 /d5000 /m"35,76,106,155,179,201,239,287,336,376,407,428,458,503,551,599,644,682,721,764,806,830,858,892,940,989,1024,1068,1110,1156,1205,1228,1274,1318,1343,1381,1426,1474,1518,1540,1583,1620,1653,1679,1723,1767,1816,1855,1902,1949,1981,2023,2072,2114,2130,2174,2214,2260,2305,2354,2403,2429,2462,2505,2548,2590,2616,2664,2699,2744,2774,2807,2855,2894,2932,2957,2998,3041,3087,3128,3165,3214,3243,3289,3322,3368,3417,3466,3494,3540,3586,3634,3659,3699,439,401,364,316,276,236,187,149,126,102,68,25,31,5,2,41,42,6,3,46,22,4,50,92,89,135,151,197,226,271,318,360,386,434,472,493,536,576,620,658,700,706,743,785,831,867,899,944,984,1009,1036,1084,1121,1161,1203,1250,1296,1298,1344,1389,1411,1441,1488,1512,1556,1590,1639,1677,1725,1773,1815,1845,1888,1920,1951,1998,2047,2049,2098,2137,2186,2231,2268,2308,2341,2374,2423,2442,2487,2527,2573,2598,2622,2661,2700,2737,2779,2809,2848,2869,2907,2956,2989,3035,3080,3089,3131,3153,3169,3215,3242,3268,3314,3347,3394,3440,3487,3499,3546,3573,3618,3667,3712,3761,3772,3819,3839,3878,3923,3972,4003,4039,4077,4116,4146,4186,4229,4266,4307,4336,4384,4429,4447,4496,4537,4573,4616,4662,4706,4747,4772,4806,4855,4892,4918,4954,3744,3793,3840,3881,3893,3941,3989,4034,4069,4104,4132,4178,4225,4258,4303,4330,4359,4408,4379,4342,4331,4301,4269,4230,4181,4141,4099,4050,4010,3965,3921,3884,3836,3814,3768,3729,3691,3650,3607,3575,3526,3501,3462,3428,3389,3353,3304,3287,3238,3189,3145,3103,3064,3053,3032,2990,2942,2904,2873,2838,2792,2769,2726,2697,2657,2634,2593,2547,2503,2461,2417,2394,2363,2317,2289,2242,2208,2172,2138,2090,2045,2002,1963,1922,1899,1858,1830,1782,1739,1691,1666,1627,1602,1555,1517,1498,1453,1405,1392,1345,1297,1255,1217,1184,1168,1120,1073,1032,986,962,927,888,839,797,755,729,688,643,628,591,550,507,485"
雖然有373箇中間點,可是隻用了兩分鐘便獲得瞭解,並且求得的解與打亂前的路徑是同一條路徑,這裏再也不列出。
3、代碼
//----------------------------------------------------------------------
// 須要包含的頭文件和使用的命名空間。
//----------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <list>
#include <queue>
#include <cstdlib>
#include <string>
#include <bitset>
#include <ctime>
#include <windows.h>
using namespace std;
//----------------------------------------------------------------------
// 節點數目和最大節點數目。
//----------------------------------------------------------------------
int V = 0;
time_t timer;
const int NODE_SIZE = 5001;
//----------------------------------------------------------------------
// 檢查是否超時。
//----------------------------------------------------------------------
bool timeout()
{
time_t cur;
return (time(&cur) - timer) > 600;
}
//----------------------------------------------------------------------
// 使用廣度優先搜索算法求解最優路徑。
//----------------------------------------------------------------------
void bfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,
int road[NODE_SIZE])
{
//------------------------------------------------------------------
// 若是超時再也不繼續搜索。
//------------------------------------------------------------------
if (timeout()) {
return;
}
//------------------------------------------------------------------
// 標識和前驅。
//------------------------------------------------------------------
static int flag[NODE_SIZE], prev[NODE_SIZE];
//------------------------------------------------------------------
// 初始化數據。
//------------------------------------------------------------------
for (int i = 0; i <= V; i++) {
flag[i] = 0;
prev[i] = 0;
}
//------------------------------------------------------------------
// 廣度優先搜索算法。
//------------------------------------------------------------------
int beg = 0, end = 1;
static int qarray[NODE_SIZE];
flag[dnode] = 1;
qarray[0] = dnode;
while (beg != end) {
int t = qarray[beg];
for (int i = 1; i <= graph[t][0]; i++) {
int element = graph[t][i];
if (flag[element] == 0) {
prev[element] = t;
flag[element] = 1;
qarray[end++] = element;
}
}
beg++;
}
//------------------------------------------------------------------
// 經過前驅得到路徑。
//------------------------------------------------------------------
if (prev[snode]) {
int element = snode;
road[0] = 1;
road[1] = element;
while (dnode != element) {
element = prev[element];
road[++road[0]] = element;
}
}
}
//----------------------------------------------------------------------
// 去掉某條路徑後再求解最優路徑。
//----------------------------------------------------------------------
void bfs_cond(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,
int cond[NODE_SIZE], int road[NODE_SIZE])
{
//------------------------------------------------------------------
// 去掉指定路徑。
//------------------------------------------------------------------
for (int i = 1; i <= cond[0]; i++) {
int cur = cond[i];
if (cur != snode && cur != dnode) {
graph[cur][0] = -graph[cur][0];
}
}
//------------------------------------------------------------------
// 求得最優解。
//------------------------------------------------------------------
bfs(graph, snode, dnode, road);
//------------------------------------------------------------------
// 恢復指定路徑。
//------------------------------------------------------------------
for (int i = 1; i <= cond[0]; i++) {
int cur = cond[i];
if (cur != snode && cur != dnode) {
graph[cur][0] = -graph[cur][0];
}
}
}
//----------------------------------------------------------------------
// 路徑是否包含全部中間節點。
//----------------------------------------------------------------------
bool has_all_mnode(int road[NODE_SIZE], int mnode[NODE_SIZE])
{
static int flag[NODE_SIZE];
for (int i = 0; i <= V; i++) {
flag[i] = 0;
}
for (int i = 1; i <= road[0]; i++) {
flag[road[i]] = 1;
}
for (int i = 1; i <= mnode[0]; i++) {
if (!flag[mnode[i]]) {
return false;
}
}
return true;
}
//----------------------------------------------------------------------
// 使用深度優先搜索算法求解最優路徑。
//----------------------------------------------------------------------
void dfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,
int temp[NODE_SIZE], int htab[NODE_SIZE], int mnode[NODE_SIZE],
int road[NODE_SIZE])
{
//------------------------------------------------------------------
// 若是超時再也不繼續搜索。
//------------------------------------------------------------------
if (timeout() || road[0] == mnode[0] + 2) {
return;
}
//------------------------------------------------------------------
// s等於d說明搜索到了目標。
//------------------------------------------------------------------
htab[snode] = 1;
temp[++temp[0]] = snode;
if (snode == dnode) {
if (has_all_mnode(temp, mnode)) {
if (road[0] == 0 || road[0] > temp[0]) {
road[0] = temp[0];
for (int j = 1; j <= temp[0]; j++) {
road[j] = temp[j];
}
}
}
htab[snode] = 0;
temp[0]--;
return;
}
//------------------------------------------------------------------
// 遍歷全部路徑。
//------------------------------------------------------------------
for (int i = 1; i <= graph[snode][0]; i++) {
if (htab[graph[snode][i]] != 1) {
dfs(graph, graph[snode][i], dnode, temp, htab, mnode, road);
}
}
//------------------------------------------------------------------
// 遍歷全部路徑。
//------------------------------------------------------------------
temp[0]--;
htab[snode] = 0;
}
//----------------------------------------------------------------------
// 使用深度優先搜索算法求解最優路徑。
//----------------------------------------------------------------------
void dfs(int graph[NODE_SIZE][NODE_SIZE], int snode, int dnode,
int mnode[NODE_SIZE], int road[NODE_SIZE])
{
static int temp[NODE_SIZE];
static int htab[NODE_SIZE];
road[0] = 0;
for (int i = 0; i <= V; i++) {
htab[i] = 0;
}
dfs(graph, snode, dnode, temp, htab, mnode, road);
}
//----------------------------------------------------------------------
// 合併兩條順序鏈接的路徑。
//----------------------------------------------------------------------
void append_path(int road[NODE_SIZE], int tail[NODE_SIZE])
{
for (int i = 1, j = road[0]; i <= tail[0]; i++, j++) {
road[j] = tail[i];
}
road[0] = road[0] + tail[0] - 1;
}
//----------------------------------------------------------------------
// 合併兩條以中間節點爲起點的路徑。
//----------------------------------------------------------------------
void form_path(int a[NODE_SIZE], int b[NODE_SIZE], int road[NODE_SIZE])
{
road[0] = a[0] + b[0] - 1;
for (int i = a[0], j = 1; i >= 1; i--, j++) {
road[j] = a[i];
}
for (int i = 1, j = a[0]; i <= b[0]; i++, j++) {
road[j] = b[i];
}
}
//----------------------------------------------------------------------
// 查看節點是否在路徑中。
//----------------------------------------------------------------------
bool is_node_in_path(int node, int road[NODE_SIZE])
{
for (int i = 1; i <= road[0]; i++) {
if (road[i] == node) {
return true;
}
}
return false;
}
//----------------------------------------------------------------------
// 根據條件查找源節點和目的節點之間包含單箇中間節點的路徑。
//----------------------------------------------------------------------
void solve_with_node_1(int graph[NODE_SIZE][NODE_SIZE], int snode,
int dnode, int mnode, int road[NODE_SIZE])
{
//------------------------------------------------------------------
// 找出以m到s、d的最短路徑,其中一條路徑不存在則知足條件的路徑也不
// 存在,兩條路徑無共同點則拼接可得最優解,有共同點則窮舉求得路徑。
//------------------------------------------------------------------
static int r1[NODE_SIZE], r2[NODE_SIZE];
road[0] = 0;
bfs(graph, mnode, snode, r1);
bfs(graph, mnode, dnode, r2);
//------------------------------------------------------------------
// 其中一條路徑不存在則知足條件的路徑也不存在。
//------------------------------------------------------------------
if (r1[0] <= 0 || r2[0] <= 0) {
return;
}
//------------------------------------------------------------------
// 兩條路徑無共同點則拼接可得最優解。
//------------------------------------------------------------------
if (r1[1] != r2[1]) {
form_path(r1, r2, road);
return;
}
//------------------------------------------------------------------
// 有共同點則先去除一段路徑後再求解另外一段路徑。
//------------------------------------------------------------------
static int r12[NODE_SIZE], r21[NODE_SIZE];
bfs_cond(graph, mnode, dnode, r1, r12);
bfs_cond(graph, mnode, snode, r2, r21);
//------------------------------------------------------------------
// 比較路徑,取最優路徑。
//------------------------------------------------------------------
if (r12[0] > 0) {
if (r21[0] > 0) {
if (r1[0] + r12[0] < r2[0] + r21[0]) {
form_path(r1, r12, road);
} else {
form_path(r21, r2, road);
}
} else {
form_path(r1, r12, road);
}
} else {
if (r21[0] > 0) {
form_path(r21, r2, road);
}
}
}
//----------------------------------------------------------------------
// 根據條件查找源節點和目的節點之間包含多箇中間節點的路徑。
//----------------------------------------------------------------------
void solve_with_node_X(int graph[NODE_SIZE][NODE_SIZE], int snode,
int dnode, int mnode[NODE_SIZE], int road[NODE_SIZE])
{
//------------------------------------------------------------------
// 若是經過某個節點的路徑包含了全部中間節點,那麼獲得解,取其中最短
// 的路徑,若是不存在經過某個中間節點的路徑,那麼不存在解。
//------------------------------------------------------------------
road[0] = 0;
for (int i = 1; i <= mnode[0]; i++) {
static int temp[NODE_SIZE];
solve_with_node_1(graph, snode, dnode, mnode[i], temp);
if (temp[0] <= 0) {
return;
}
if (has_all_mnode(temp, mnode)) {
if (road[0] == 0 || road[0] > temp[0]) {
road[0] = temp[0];
for (int j = 1; j <= temp[0]; j++) {
road[j] = temp[j];
}
if (road[0] == mnode[0] + 2) {
return;
}
}
}
}
//------------------------------------------------------------------
// 上面若能獲得解確定是最優解。
//------------------------------------------------------------------
if (road[0] > 0) {
return;
}
//------------------------------------------------------------------
// 依次遍歷s->m1->...->d,s->m2->...->d,到s->mn->...->d。
//------------------------------------------------------------------
for (int i = 1; i <= mnode[0]; i++) {
static int rsmy[NODE_SIZE];
bfs(graph, snode, mnode[i], rsmy);
if (rsmy[0] > 0) {
//----------------------------------------------------------
// 搜索路徑s->mX->...->mY。
//----------------------------------------------------------
int node = mnode[i];
for (int j = 1; j <= mnode[0]; j++) {
if (!is_node_in_path(mnode[j], rsmy)) {
int tnode;
static int rm2m[NODE_SIZE];
tnode = mnode[j];
rsmy[++rsmy[0]] = dnode;
bfs_cond(graph, node, tnode, rsmy, rm2m);
rsmy[0]--;
if (rm2m[0] <= 0) {
node = -1;
break;
}
append_path(rsmy, rm2m);
node = tnode;
}
}
if (node != -1) {
//------------------------------------------------------
// 搜索路徑mY->d。
//------------------------------------------------------
static int rmyd[NODE_SIZE];
bfs_cond(graph, node, dnode, rsmy, rmyd);
if (rmyd[0] > 0) {
append_path(rsmy, rmyd);
//--------------------------------------------------
// 保存搜索到的最短路徑。
//--------------------------------------------------
if (road[0] == 0 || road[0] > rsmy[0]) {
road[0] = rsmy[0];
for (int j = 1; j <= rsmy[0]; j++) {
road[j] = rsmy[j];
}
if (road[0] == mnode[0] + 2) {
return;
}
}
}
}
}
}
//------------------------------------------------------------------
// 若是找到了路徑就返回吧,雖然這裏找到的不必定是最優的。
//------------------------------------------------------------------
if (road[0] > 0) {
return;
}
//------------------------------------------------------------------
// 若是仍是找不到,那麼只有祭出最強法寶——深度優先搜索。
//------------------------------------------------------------------
dfs(graph, snode, dnode, mnode, road);
}
//----------------------------------------------------------------------
// 根據條件查找源節點和目的節點之間的路徑。
//----------------------------------------------------------------------
int solve(const char *iname, const char *oname, int snode, int dnode,
int mnode[NODE_SIZE])
{
//------------------------------------------------------------------
// 圖的鄰接矩陣。
//------------------------------------------------------------------
static int graph[NODE_SIZE][NODE_SIZE];
//------------------------------------------------------------------
// 清空圖。
//------------------------------------------------------------------
for (int i = 0; i < NODE_SIZE; i++)
for (int j = 0; j < NODE_SIZE; j++)
graph[i][j] = 0;
//------------------------------------------------------------------
// 從輸入文件讀取圖。
//------------------------------------------------------------------
ifstream ifs(iname);
if (ifs.is_open()) {
int a, b;
string title;
getline(ifs, title);
while (!ifs.eof()) {
char c;
ifs >> a >> c >> b;
graph[a][++graph[a][0]] = b;
graph[b][++graph[b][0]] = a;
V = V < a ? a : (V < b ? b : V);
}
ifs.close();
} else {
return -1;
}
//------------------------------------------------------------------
// 路徑。
//------------------------------------------------------------------
static int road[NODE_SIZE];
//------------------------------------------------------------------
// 搜索符合條件的路徑。
//------------------------------------------------------------------
if (mnode[0] <= 0)
{
//--------------------------------------------------------------
// 若是沒有中間節點就求s到d的最短路徑。
//--------------------------------------------------------------
bfs(graph, snode, dnode, road);
}
else
{
//--------------------------------------------------------------
// 若是s到d的沒有路徑就不用繼續了。
//--------------------------------------------------------------
bfs(graph, snode, dnode, road);
if (road[0] > 0)
{
//----------------------------------------------------------
// 若是搜索到的路徑包含了全部中間節點,那麼這就是最優解,其
// 它狀況下用通常的方法求解。
//----------------------------------------------------------
if (!has_all_mnode(road, mnode)) {
road[0] = 0;
solve_with_node_X(graph, snode, dnode, mnode, road);
}
}
}
//------------------------------------------------------------------
// 輸出結果。
//------------------------------------------------------------------
ofstream ofs(oname);
if (ofs.is_open()) {
ofs << "main:";
for (int i = 1; i <= road[0]; i++) {
ofs << " " << road[i];
if (i != road[0])
ofs << ",";
}
ofs << endl;
} else {
return -1;
}
//------------------------------------------------------------------
// 完成。
//------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------
// 從字符串中獲取中間節點列表。
//----------------------------------------------------------------------
void get_mnode_list(const char *str, int mnode[NODE_SIZE])
{
mnode[0] = 0;
while (*str)
{
while (*str == ',') str++;
mnode[++mnode[0]] = atoi(str);
while (*str >= '0' && *str <= '9') str++;
}
}
//----------------------------------------------------------------------
// 程序入口,argc是命令行參數個數,argv是命令行參數表。
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
//------------------------------------------------------------------
// 默認的輸入文件、輸出文件、源節點、目的節點、約束條件等參數。
//------------------------------------------------------------------
int snode = -1; // 默認源節點
int dnode = -1; // 默認目的節點
int mnode[NODE_SIZE]; // 中間節點列表
const char *iname = "in.txt"; // 默認輸入文件
const char *oname = "out.txt"; // 默認輸出文件
//------------------------------------------------------------------
// 保存程序開始運行時的時間。
//------------------------------------------------------------------
timer = time(&timer);
//------------------------------------------------------------------
// 根據命令行參數肯定輸入文件、輸出文件、源節點、目的節點、約束條件
// 等參數。
//------------------------------------------------------------------
while (*argv) {
char *str = *argv++;
if (*str++ == '/') {
switch (*str++) {
case 'f':
case 'F':
if (*str) {
iname = str;
} else {
iname = *argv++;
}
break;
case 's':
case 'S':
if (*str) {
snode = atoi(str);
} else {
snode = atoi(*argv++);
}
break;
case 'd':
case 'D':
if (*str) {
dnode = atoi(str);
} else {
dnode = atoi(*argv++);
}
break;
case 'm':
case 'M':
if (*str) {
get_mnode_list(str, mnode);
} else {
get_mnode_list(*argv++, mnode);
}
break;
case 'o':
case 'O':
if (*str) {
oname = str;
} else {
oname = *argv++;
}
break;
default:
break;
}
}
}
//------------------------------------------------------------------
// 調用solve函數解決問題。
//------------------------------------------------------------------
return solve(iname, oname, snode, dnode, mnode);
}