-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathq1_2.cpp
279 lines (240 loc) · 5.89 KB
/
q1_2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#include <iostream>
#include <vector>
#include <limits>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::numeric_limits;
// 1. 我爱北大
// 无向图
// 两点之间可能存在多条路线
struct Edge {
// 相邻点
int adjVex;
Edge* nextArc;
int weight;
Edge(int a, int w) :adjVex(a), weight(w), nextArc(NULL) {}
Edge() :adjVex(0), weight(0), nextArc(NULL) {}
};
struct AdjList {
string data;
Edge* firstArc;
AdjList() :firstArc(NULL) {}
};
class Graph {
private:
int numVertex = 0;
int numEdge = 0;
// 图的顶点访问标记
bool mark[30];
// 存放图中顶点的入度
int Indegree[30];
// 邻接表
AdjList vertices[50];
public:
int verticesNum();
int edgesNum();
// 顶点的第一条关联边
Edge* firstEdge(int vertex);
// 下一条兄弟边
Edge* nextEdge(Edge* preEdge);
void addVertex(string data);
void setEdge(int fromVertex, int toVertex, int weight);
bool isVisited(int vertices);
void setVisited(int vertex, bool value);
int toVertex(Edge* edge);
int Weight(Edge* edge);
string getVertex(int vertex);
int indexOf(string data);
};
int Graph::verticesNum() {
return numVertex;
}
int Graph::edgesNum() {
return numEdge;
}
Edge* Graph::firstEdge(int vertex) {
return this->vertices[vertex].firstArc;
}
Edge* Graph::nextEdge(Edge* preEdge) {
return preEdge->nextArc;
}
void Graph::addVertex(string data) {
this->vertices[numVertex++].data = data;
}
void Graph::setEdge(int fromVertex, int toVertex, int weight) {
// 替代旧值
bool flag = false;
Edge* curEdge = this->vertices[fromVertex].firstArc;
while (curEdge != NULL) {
if (this->toVertex(curEdge) == toVertex) {
flag = true;
if (weight < this->Weight(curEdge)) {
curEdge->weight = weight;
}
break;
}
curEdge = curEdge->nextArc;
}
curEdge = this->vertices[toVertex].firstArc;
while (curEdge != NULL) {
if (this->toVertex(curEdge) == fromVertex) {
flag = true;
if (weight < this->Weight(curEdge)) {
curEdge->weight = weight;
}
break;
}
curEdge = curEdge->nextArc;
}
if (flag) {
return;
}
// 添加边,如果不存在重复
Edge* newEdge = new Edge(toVertex, weight);
// 放到边表的最后一个
curEdge = this->vertices[fromVertex].firstArc;
if (curEdge == NULL) {
this->vertices[fromVertex].firstArc = newEdge;
} else {
while (curEdge->nextArc != NULL) {
curEdge = curEdge->nextArc;
}
curEdge->nextArc = newEdge;
}
this->numEdge++;
newEdge = new Edge(fromVertex, weight);
// 放到边表的最后一个
curEdge = this->vertices[toVertex].firstArc;
if (curEdge == NULL) {
this->vertices[toVertex].firstArc = newEdge;
} else {
while (curEdge->nextArc != NULL) {
curEdge = curEdge->nextArc;
}
curEdge->nextArc = newEdge;
}
this->numEdge++;
}
bool Graph::isVisited(int vertex) {
return mark[vertex];
}
void Graph::setVisited(int vertex, bool value) {
mark[vertex] = value;
}
int Graph::toVertex(Edge* edge) {
return edge->adjVex;
}
int Graph::Weight(Edge* edge) {
return edge->weight;
}
string Graph::getVertex(int vertex) {
return this->vertices[vertex].data;
}
int Graph::indexOf(string data) {
for (int i = 0; i < numVertex; i++) {
if (this->vertices[i].data == data) {
return i;
}
}
return -1;
}
struct Dist {
int length; // 当前顶点的单源最短路径
int pre; // 路径中的前一个顶点,用于存储最短路径
};
void floyd(Graph& graph, Dist** &dist) {
// 初始化
dist = new Dist*[graph.verticesNum()];
for (int i = 0; i < graph.verticesNum(); i++) {
dist[i] = new Dist[graph.verticesNum()];
}
for (int i = 0; i < graph.verticesNum(); i++) {
for (int j = 0; j < graph.verticesNum(); j++) {
if (i == j) {
dist[i][j].length = 0;
dist[i][j].pre = i;
} else {
dist[i][j].length = numeric_limits<int>::max();
dist[i][j].pre = -1;
}
}
}
// 更新直接路径
for (int vex = 0; vex < graph.verticesNum(); vex++) {
for (Edge* edge = graph.firstEdge(vex); edge != NULL; edge = graph.nextEdge(edge)) {
dist[vex][graph.toVertex(edge)].length = graph.Weight(edge);
dist[vex][graph.toVertex(edge)].pre = vex;
}
}
// 用每个顶点作为中间点更新,原两点间的路径
for (int v = 0; v < graph.verticesNum(); v++) {
for (int i = 0; i < graph.verticesNum(); i++) {
for (int j = 0; j < graph.verticesNum(); j++) {
// 因为将不连通的距离设置为了int最大值
// 这里是为了防止溢出
if (dist[i][v].length != numeric_limits<int>::max() &&
dist[v][j].length != numeric_limits<int>::max() &&
dist[i][j].length > dist[i][v].length + dist[v][j].length) {
dist[i][j].length = dist[i][v].length + dist[v][j].length;
dist[i][j].pre = dist[v][j].pre;
}
}
}
}
}
int main(int argc, char *argv[]) {
Graph graph;
int p = 0;
cin >> p;
for (int i = 0; i < p; i++) {
string site;
cin >> site;
graph.addVertex(site);
}
int q = 0;
cin >> q;
for (int i = 0; i < q; i++) {
string site1;
string site2;
int weight = 0;
cin >> site1 >> site2 >> weight;
graph.setEdge(graph.indexOf(site1), graph.indexOf(site2), weight);
}
// 计算两点间最小路径
Dist** dist = NULL;
floyd(graph, dist);
int r = 0;
cin >> r;
for (int i = 0; i < r; i++) {
string site1;
string site2;
cin >> site1 >> site2;
int vex1 = graph.indexOf(site1);
int vex2 = graph.indexOf(site2);
// 从后往前推路径
vector<int> route;
while (vex2 != vex1) {
route.push_back(vex2);
vex2 = dist[vex1][vex2].pre;
}
route.push_back(vex1);
// 输出
for (int i = route.size() - 1; i >= 1; i--) {
// 找到边的权重
int weight = 0;
for (Edge* edge = graph.firstEdge(route[i]); edge != NULL; edge = graph.nextEdge(edge)) {
if (graph.toVertex(edge) == route[i - 1]) {
weight = graph.Weight(edge);
break;
}
}
cout << graph.getVertex(route[i]) << "->(" << weight << ")->";
}
cout << graph.getVertex(route[0]) << endl;
}
return 0;
}