-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsolve.sql
More file actions
executable file
·87 lines (75 loc) · 2.4 KB
/
solve.sql
File metadata and controls
executable file
·87 lines (75 loc) · 2.4 KB
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
USE practice;
DROP PROCEDURE IF EXISTS dijkstra;
DROP TABLE IF EXISTS CulcGraph;
DELIMITER //
CREATE PROCEDURE dijkstra(IN startV INT, IN goalV INT, OUT result INT)
BEGIN
-- nowV : 探索中の頂点
DECLARE nowV INT;
-- nowTotal : 前までの探索でnowVにたどり着くまでにかかったコスト合計
DECLARE nowTotal INT;
DECLARE E_MAX INT;
DECLARE V_INF INT;
DECLARE E_INF INT;
DECLARE INF INT;
SELECT MAX(cost) INTO E_MAX FROM edges;
-- 同じ頂点を2度訪れることはない
SELECT COUNT(id)*E_MAX INTO V_INF FROM vertices;
-- 同じ辺を2度使うことはない
SELECT COUNT(id)*E_MAX INTO E_INF FROM edges;
-- INF はグラフのスタート地点からゴール地点まで一筆で行った時、絶対に超えない値とする
SET INF = CASE WHEN V_INF > E_INF THEN V_INF + 1 ELSE E_INF + 1 END;
UPDATE vertices SET cost = 0 WHERE id = startV;
DROP TABLE IF EXISTS CulcGraph;
CREATE TABLE CulcGraph
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
tmpTotal INT UNSIGNED NOT NULL,
tmpV INT UNSIGNED NOT NULL,
INDEX tmpVT_idx(tmpV, tmpTotal),
INDEX tmpTV_idx(tmpTotal, tmpV),
PRIMARY KEY(id)
);
INSERT INTO CulcGraph (tmpTotal, tmpV) VALUES (0, startV);
label1: LOOP
IF (SELECT COUNT(*) FROM CulcGraph) = 0 THEN
LEAVE label1;
END IF;
SELECT tmpTotal, tmpV
INTO nowTotal, nowV
FROM CulcGraph
ORDER BY tmpTotal ASC
LIMIT 1;
DELETE FROM CulcGraph
WHERE tmpTotal = nowTotal
AND tmpV = nowV;
IF (SELECT cost FROM vertices WHERE id = nowV) < nowTotal THEN
ITERATE label1;
END IF;
-- index をつけるクエリ
INSERT INTO CulcGraph(tmpTotal, tmpV)
(SELECT nowTotal + tmpEdges.cost, tmpEdges.dest
FROM (
SELECT MIN(edges.cost) AS cost, edges.dest
FROM edges
WHERE edges.src = nowV
GROUP BY edges.dest
) tmpEdges
INNER JOIN
vertices
ON tmpEdges.dest = vertices.id
WHERE COALESCE(vertices.cost, INF) > nowTotal + tmpEdges.cost
);
UPDATE CulcGraph cg
INNER JOIN
vertices Vs
ON cg.tmpV = Vs.id
SET Vs.cost = CASE WHEN COALESCE(Vs.cost, INF) > tmpTotal THEN tmpTotal
ELSE Vs.cost
END;
END LOOP label1;
SET result = (SELECT cost FROM vertices WHERE id = goalV);
DROP TABLE CulcGraph;
END
//
DELIMITER ;