#include<iostream>
#include<fstream>
#include<queue>
#include<stack>
using namespace std;
#pragma warning(disable:4996)
#define MAXSTATION 5200
typedef struct Station
{
int Num = -1;//从0开始编号
char Name[52];
int bus_count = 0;//经过该站的bus数
int bus_num[100];//经过该站bus的编号;是有序的
}Station;
typedef struct Bus
{
int Num = 0;//某路公交车
int station_count = 0;//此bus经过的站总数
int station_num[100];//无序,站的编号
};
int Find_Station_Num(char station_name[]);
int Station_Find_Bus(int start, int end, int two_station_bus[]);//station[start]->station[end]
bool Find_Min_Transfer(char station_start[], char station_end[]);
bool Find_Min_Station(char station_start[], char station_end[]);
void Init(fstream &fp);
void Show_Route(int path[], int n);
void Show_boundary()
{
cout << "***************************************************************************************************" << endl;
return;
}
void transfor_path_to_detail(int path[], int n, int detailpath[], int &len);
int Find_Bus_From_Num(int n);//找Num为n的bus,找到返回其在数组中的编号,否则返回-1;
Station station[MAXSTATION];
Bus bus[1000];
int father[MAXSTATION] = { 0 };
int a[MAXSTATION][MAXSTATION] = { 0 };//非零代表ij之间有非零辆车
int b[MAXSTATION][MAXSTATION] = { 0 };//两个站点之间是否直接相邻,非零代表相邻借助bus的种类数
int station_sum_num = 0;
int main()
{
fstream fp;
fp.open("4.txt", ios::in);
if (fp.fail())
{
cout << "fail to open the file";
system("PAUSE");
exit(0);
}
Init(fp);
char s_start[52];
char s_end[52];
cout << "请输入始点:";
cin >> s_start;
cout << endl << "请输入终点:";
cin >> s_end;
/*bool tell = Find_Min_Transfer(s_start, s_end);
if (tell == false)
cout << "不可达" << endl;
*/
Find_Min_Station(s_start, s_end);
system("PAUSE");
}
int Find_Station_Num(char station_name[])//TODO:后期用个hash表来找 // 站名找其编号(也是数组下标)
{
int index = -1;
for (int i = 0; station[i].Num != -1; i++)
{
if (strcmp(station_name, station[i].Name) == 0)
{
index = i;
break;
}
}
return index;
}
int Station_Find_Bus(int start, int end,int two_station_bus[])//station[start]->station[end],之间的直达bus的编号 ,bus的数量再邻接矩阵中可得到
{ //start,end 为站点的编号
int n = a[start][end];
int k = 0;
for (int i = 0; i < station[start].bus_count; i++)
{
for (int j = 0; j < station[end].bus_count; j++)
{
if (station[start].bus_num[i] == station[end].bus_num[j])
{
two_station_bus[k++] = station[start].bus_num[i];
if (k == n) return n;
}
if (station[start].bus_num[i] < station[end].bus_num[j])
break;
}
}
}
bool Find_Min_Transfer(char station_start[], char station_end[])//BFS,找到end就break,
{
int start = Find_Station_Num(station_start);
int end = Find_Station_Num(station_end);
if (start == -1 || end == -1)
{
cout << "站点输入错误" << endl;
return false;
}
//BFS
if (a[start][end] != 0)// 直达
{
int path[2];
path[0] = start;
path[1] = end;
cout << "最少换乘次数路线如下:" << endl;
Show_boundary();
Show_Route(path, 2);
Show_boundary();
cout << "无需换乘,直达" << endl;
return true;
}
else
{
bool visit[5200]; //init
memset(visit, false, 5200);
memset(father, 0, 5200);
bool success = false;
queue<int>q;
q.push(start);
visit[start] = true;
father[start] = -1;
while (!q.empty())
{
queue<int>te;
while (!q.empty()) //同等次数换乘的站
{
te.push(q.front());
q.pop();
}
while (!te.empty())
{
int k = te.front();
te.pop();
for (int i = 0; i < station_sum_num; i++)
{
if (visit[i] == false && a[k][i] != 0)
{
visit[i] = true;
father[i] = k;//后面好找路线
q.push(i);
}
}
}
for (int i = 0; i < q.size(); i++)//判断是否与end终点连通
{
if (a[q.front()][end] != 0)
{
success = true;
}
int k = q.front();
q.pop();
q.push(k);
}
if (success)
break;
}
if (success == false)
{
cout << "没有线路连通两站" << endl;
return false;
}
cout << "最少换乘次数路线如下:" << endl;
Show_boundary();
int time = 0; //换乘次数
for (int i = 0; i < q.size(); i++)
{
int k = q.front();
q.pop();
if (a[k][end] != 0)//可达终点,q队列中放在可能可达终点的前一站
{
int len = 0;
int path[100];
stack<int>temp;
for (int j = k; father[j] != -1; j = father[j])
{
temp.push(j);
}
temp.push(start);
len = temp.size();
for (int j = 0; j < len; j++)
{
path[j] = temp.top();
temp.pop();
}
path[len++] = end; //path中存起始点站,以及到达他们的中转站
Show_Route(path, len);
time = len - 2;
}
}
Show_boundary();
cout << "换乘次数:" << time << "次" << endl;
}
return true;
}
bool Find_Min_Station(char station_start[], char station_end[])
{
int PATH[5000];
int min_len = 1000;
int detailed_path[5000];
// int **detailed_path = (int**)malloc(100*sizeof(int*));
int detailed_path_len = 0;
int start = Find_Station_Num(station_start);
int end = Find_Station_Num(station_end);
if (start == -1 || end == -1)
{
cout << "站点输入错误" << endl;
return false;
}
//BFS
if (a[start][end] != 0)// 直达
{
int path[2];
path[0] = start;
path[1] = end;
// detailed_path[path_number] = (int*)malloc(100 * sizeof(int));
transfor_path_to_detail(path, 2, detailed_path, detailed_path_len);
if (detailed_path_len < min_len)
{
min_len = detailed_path_len;
for (int i = 0; i < min_len; i++)
{
PATH[i] = detailed_path[i];
}
}
}
else
{
bool visit[5200]; //init
for (int x = 0; x < 5200; x++)
visit[x] = false;
memset(father, 0, 5200*sizeof(int));
queue<int>q;
q.push(start);
visit[start] = true;
father[start] = -1;
while (!q.empty())
{
int k = q.front();
q.pop();
for (int i = 0; i < station_sum_num; i++)
{
if (visit[i] == false && a[k][i] != 0)
{
visit[i] = true;
father[i] = k;//后面好找路线
q.push(i);
if (a[i][end] != 0)
{
stack<int>temp;
temp.push(end);
for (int j = i; father[j] != -1; j = father[j])
{
temp.push(j);
}
temp.push(start);
int n = temp.size();
int path[500];
for (int j = 0; j < n; j++)
{
path[j] = temp.top();
temp.pop();
}
// detailed_path[path_number] = (int*)malloc(100 * sizeof(int));
transfor_path_to_detail(path, n, detailed_path, detailed_path_len);
if (detailed_path_len < min_len)
{
min_len = detailed_path_len;
for (int i = 0; i < min_len; i++)
{
PATH[i] = detailed_path[i];
}
}
}
}
}
}
}
//Print
cout << "经过最少站点数为:" << min_len << "个\n结果如下:\n";
for (int j = 0; j < min_len - 1; j++)
{
cout << station[PATH[j]].Name << "->";
}
cout << station[PATH[min_len - 1]].Name << endl;
return true;
}
void Init(fstream &fp)
{
int buscount = 0;
while (!fp.eof())
{
char num[8];//几路bus
fp >> num;
if (fp.fail()) break;
for (int i = 0; i < 8; i++)
{
if (num[i] >= '0' && num[i] <= '9')
bus[buscount].Num = bus[buscount].Num * 10 + num[i] - '0';
else
break;
}
fp.ignore();// 空格
fp.ignore();
fp.ignore();
char str[1000];
fp.getline(str, 1000);
int len = strlen(str);
int k = 0;
char s[50];//每个站
for (int i = 0; i <= len; i++)
{
if (str[i] != ',' && str[i] != '\0')
{
s[k++] = str[i];
}
else//一个站点全部读入完
{
s[k] = '\0';
k = 0;
int nu = Find_Station_Num(s);
if (nu == -1)//新站
{
//维护station
station[station_sum_num].Num = station_sum_num;
strcpy(station[station_sum_num].Name, s);
station[station_sum_num].bus_num[station[station_sum_num].bus_count] = bus[buscount].Num;
station[station_sum_num].bus_count++;
station_sum_num++;
//维护bus
bus[buscount].station_num[bus[buscount].station_count] = station_sum_num - 1;
bus[buscount].station_count++;
}
else
{
//维护station
station[nu].bus_num[station[nu].bus_count] = bus[buscount].Num;
station[nu].bus_count++;
//只维护bus
bus[buscount].station_num[bus[buscount].station_count] = nu;
bus[buscount].station_count++;
}
}
}
buscount++;
}
//memset
for(int i = 0; i < station_sum_num; i++)
for (int j = 0; j < station_sum_num; j++)
{
a[i][j] = 0;
b[i][j] = 0;
}
//update a[][]
for (int k = 0; k < buscount; k++)
{
for (int i = 0; i < bus[k].station_count; i++)
{
for (int j = 0; j < bus[k].station_count; j++)
{
a[bus[k].station_num[i]][bus[k].station_num[j]]++;
}
}
}
for (int i = 0; i < station_sum_num; i++)
a[i][i] = 0;
//update b[][]
for (int k = 0; k < buscount; k++)
{
for (int i = 1; i < bus[k].station_count; i++)
{
b[bus[k].station_num[i-1]][bus[k].station_num[i]]++;
}
}
return;
}
void Show_Route(int path[], int n)
{
for (int i = 0; i < n - 1; i++)
{
cout << station[path[i]].Name << " 乘坐 ";
int tsb[100];
memset(tsb, 0, 100);
Station_Find_Bus(path[i], path[i + 1], tsb);
for (int j = 0; tsb[j]!=0; j++)
{
cout << tsb[j] << " ";
}
if (tsb[1] != 0)
cout << "(其中任一)";
cout << "路公交车到 ";
}
cout << station[path[n - 1]].Name << endl;
return;
}
void transfor_path_to_detail(int path[], int n, int detailpath[], int &len)
{
len = 0;
for (int k = 0; k < n - 1; k++)//找path[k]和path[k+1]两个站点之间的最少站
{
int part_len = 0;
int k_bus_num = 0;//两站之间的公交车数目,可根据a[][]来判断是否将全部公交车遍历完,为了提前结束循环
for (int i = 0; i < station[path[k]].bus_count; i++)
{
for (int j = 0; j < station[path[k + 1]].bus_count; j++)
{
if (station[path[k]].bus_num[i] == station[path[k + 1]].bus_num[j])
{
k_bus_num++;
if (k_bus_num == 1)
{
int te_bus = Find_Bus_From_Num(station[path[k]].bus_num[i]);
int start_index = 0;
for (int x = 0; x < bus[te_bus].station_count; x++)//定位
{
if (bus[te_bus].station_num[x] == path[k])
{
start_index = x;
break;
}
}
for (int x = start_index; x < bus[te_bus].station_count; x++)//正序
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
detailpath[len++] = bus[te_bus].station_num[x];
part_len++;
}
if (detailpath[len + start_index - bus[te_bus].station_count] == path[k])//逆序
{
part_len = 0;
len = len + start_index - bus[te_bus].station_count;
for (int x = start_index; x >= 0; x--)
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
detailpath[len++] = bus[te_bus].station_num[x];
part_len++;
}
}
}
else
{
bool dir = true;
int te_len = 0;
int te_bus = Find_Bus_From_Num(station[path[k]].bus_num[i]);
int start_index = 0;
for (int x = 0; x < bus[te_bus].station_count; x++)//定位
{
if (bus[te_bus].station_num[x] == path[k])
{
start_index = x;
break;
}
}
for (int x = start_index; x < bus[te_bus].station_count; x++)//正序
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
te_len++;
}
if (bus[te_bus].station_count-start_index == te_len)//逆序
{
te_len = 0;
dir = false;
for (int x = start_index; x >= 0; x--)
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
te_len++;
}
}
if (te_len < part_len)
{
len = len - part_len;
if (dir)
{
for (int x = start_index; x < bus[te_bus].station_count; x++)
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
detailpath[len++] = bus[te_bus].station_num[x];
}
}
else
{
for (int x = start_index; x >= 0; x--)
{
if (bus[te_bus].station_num[x] == path[k + 1]) break;
detailpath[len++] = bus[te_bus].station_num[x];
}
}
part_len = te_len;
}
}
if (k_bus_num == a[path[k]][path[k + 1]])
{
i = station[path[k]].bus_count;
break;
}
break;
}
}
}
}
detailpath[len++] = path[n - 1];
return;
}
int Find_Bus_From_Num(int n)
{
for (int i = 0; i < 1000; i++)
{
if (bus[i].Num == n)
return i;
}
return -1;
}