一、设计方案
复赛增加了一个条件,也正是这个条件提升了问题的难度。诸如BFS等最短路径算法均不能求解经过指定顶点的最短路径。虽然如此,但是可以考虑将这个问题转换为求解最短路径问题。
首先计算s到d的最短路径,如果包含了所有的中间节点,显然这就是符合条件的最优解了。如果没有找到最短路径,说明不存在一条路径。比较复杂的情况是找到了最短路径,但是没有包含所有中间节点。
如果只有一个中间节点m,可以将路径从中间节点处分为两段。分别求两段的最短路径,如果两段最短路径除了m外没有公共节点,那么合并这两段路径可以得到最优解。两段有除了m外的其它公共点就先计算其中一段路径的最短路径,从图上去掉这个路径所包含的节点,然后再求第二段路径,合并可以得到一条从s到d经过m的路径。两次计算可以求得s到d经过m的最短路径。
如果包含多个中间节点就更为复杂了。这种情况下,考虑计算经过其中一个中间节点的路径。如果不存在经过某个节点的路径那么就不存在解。如果某条路径包含了所有节点,那么这条路径是一个解。求出来所有这样的解,其中的最短路径是最优解。如果不存在某条路径包含了所有的中间节点,那么可以知道,从s到d经过每一个中间点都存在一条路径,在这种情况下,可以遍历m1,m2,…,mn依次求解s->m1->…->d,s->m2->…->d等,最后求得满足条件的最短路径,但这样获得的路径不能保证是最短路径。
如果以上方法均不能求得结果,那么只有祭出最强神器——深度优先搜索。深度优先搜索能够遍历所有路径,可以获得符合要求的最短路径。虽然能够求得最优解,但是时间复杂度较高,在边数较少的情况下可以快速求得解。为了能在10分钟内得到解,在计算的过程中检查是否超时。
二、性能
本程序中,bfs的时间复杂度是O(E+V),其中E是边数,V是节点数,解决问题需要调用O(N²)次bfs(虽然最后采用dfs来保底,但是主要是以bfs来解决问题的),其中N为中间点数目,总的运行时间是O((E+V)N²)。
首先,使用示例数据进行测试。
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个中间点,但是只用了两分钟便得到了解,而且求得的解与打乱前的路径是同一条路径,这里不再列出。
三、代码
//----------------------------------------------------------------------
// 需要包含的头文件和使用的命名空间。
//----------------------------------------------------------------------
#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);
}