-
Notifications
You must be signed in to change notification settings - Fork 1
/
P2865.cpp
152 lines (140 loc) · 3.59 KB
/
P2865.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
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
using namespace std;
#define NO_VALUE -1
typedef unsigned short Vertex; //顶点
//邻接点结构体
struct AdjNode {
Vertex adj_v; //邻接点
int adj_weight; //邻接边权重
AdjNode(Vertex adj_v, int adj_weight) : adj_v(adj_v), adj_weight(adj_weight) {}
};
//计算次短路的类
class SecondShortestPath {
public:
/* 计算次短路。
@param graph 图
@param nv 顶点数
@param src 源
@param des 终点
@return int 次短路长度
*/
int getSecondShortestPath(vector<AdjNode> * graph, int nv, int src, int des);
private:
/* 计算源到每个顶点的最短距离。
@param graph 图
@param nv 顶点数
@param src 源
@param dist 存储最短距离的数组(传出)
@return void
*/
void dijkstra(vector<AdjNode> * graph, int nv, int src, int *dist);
/* A*计算次短路。
@param graph 图
@param nv 顶点数
@param src 源
@param des 终点
@param h 估值数组
@return int 次短路长度
*/
int astar(vector<AdjNode>* graph, int nv, int src, int des, int *h);
//优先队列使用的结构体
//dijkstra优先队列使用
struct PriorityNode {
Vertex v;
int dist;
PriorityNode(Vertex v, int dist) : v(v), dist(dist) {}
};
//A*优先队列使用
struct AStarNode : PriorityNode {
//PriorityNode::dist 为f
int g;
AStarNode(Vertex v, int g, int f) : PriorityNode(v, f), g(g) {}
};
struct cmp {
bool operator () (PriorityNode& a, PriorityNode& b) {
return a.dist > b.dist;
}
};
};
int SecondShortestPath::getSecondShortestPath(vector<AdjNode>* graph, int nv, int src, int des) {
int *h = new int[nv];
//dijkstra计算des到每个顶点的最短距离,作为h
dijkstra(graph, nv, des, h);
//计算次短路
int result = astar(graph, nv, src, des, h);
free(h);
return result;
}
void SecondShortestPath::dijkstra(vector<AdjNode>* graph, int nv, int src, int *dist) {
fill(dist, dist + nv, NO_VALUE);
bool *collected = new bool[nv];
fill(collected, collected + nv, false);
dist[src] = 0;
priority_queue<PriorityNode, vector<PriorityNode>, cmp> q;
q.push(PriorityNode(src, 0));
Vertex min_v, adj_v;
int adj_weight, tmp_dist;
while (!q.empty()) {
min_v = q.top().v;
q.pop();
if (collected[min_v]) continue;
collected[min_v] = true;
for (auto it = graph[min_v].begin(); it != graph[min_v].end(); it++) {
//遍历邻接点
adj_v = it->adj_v;
if (!collected[adj_v]) {
adj_weight = it->adj_weight;
tmp_dist = dist[min_v] + adj_weight;
if (tmp_dist < dist[adj_v] || dist[adj_v] == NO_VALUE) {
dist[adj_v] = tmp_dist;
q.push(PriorityNode(adj_v, tmp_dist));
}
}
} //for
} //while
free(collected);
}
int SecondShortestPath::astar(vector<AdjNode>* graph, int nv, int src, int des, int *h) {
priority_queue<AStarNode, vector<AStarNode>, cmp> q;
q.push(AStarNode(src, 0, h[src]));
Vertex min_v, adj_v;
int min_g, tmp_g, count = 0;
while (!q.empty()) {
min_v = q.top().v;
min_g = q.top().g;
q.pop();
if (min_v == des) {
if (++count == 2) {
//第二次弹出des
while (!q.empty()) q.pop();
return min_g;
}
}
for (auto it = graph[min_v].begin(); it != graph[min_v].end(); it++) {
//遍历邻接点
adj_v = it->adj_v;
tmp_g = min_g + it->adj_weight;
q.push(AStarNode(adj_v, tmp_g, tmp_g + h[adj_v]));
}
} //while
return NO_VALUE;
}
int main() {
int n, r;
scanf("%d %d", &n, &r);
vector<AdjNode> *graph = new vector<AdjNode>[n];
for (int i = 0, a, b, d; i < r; i++) {
scanf("%d %d %d", &a, &b, &d);
a--; b--;
graph[a].push_back(AdjNode(b, d));
graph[b].push_back(AdjNode(a, d));
}
SecondShortestPath ssp;
printf("%d", ssp.getSecondShortestPath(graph, n, 0, n - 1));
for (int i = 0; i < n; i++)
vector<AdjNode>().swap(graph[i]);
return 0;
}