Graph Theory
Author: chuong3a, nick yahoo: chuong3a
Undirected Graph ... 2
Directed Graph ... 4
Minimal Spanning Tree ... 6
Weight Matrix ... 10
The types of Graph ... 10
Prims Algorithm ... 17
Prim Algorithm code C++ with Notation ... 19
Code Maple Prims ... 20
Kruskal Algorithm Code C++ 1 ... 23
Kruskal Algorithm Code C++ 2 ... 25
Code Maple Kruskal ... 27
Depth First Search ... 29
Code Maple DFS ... 30
Depth First Search Algorithm ... 31
Breadth First Search Algorithm ... 33
BFS Code Maple ... 34
BFS Code C++ ... 35
Dijkstra Algorithm ... 37
Code Dijkstra Algorithm ... 37
Code Maple Dijsktra ... 40
Dijkstra Algorithm run by hand ... 41
Bellman-Ford Algorithm ... 45
BellmanFord Code 2. ... 47
Bellman-Ford run by hand ... 48
Floyd Code ... 50
Code Maple Floyd 1 ... 52
Code Maple Floyd 2 ... 52
Chu trình Euler ... 53
Euler Cycle Maple Code 2 ... 55
Stack: ... 56
Euler Cycle C++ Code ... 57
Chu trình Hamilton ... 59
Hamilton Maple Code ... 60
Code Hamilton C++ ... 62
Dijsktra 2 ... 67
1/ 4 người bất kì trong số n > 3 người đều quen với 3 người còn lại. CM rằng luôn có 1 người quen với n – 1 người còn lại.
Solution:
- Giả sử bài toán đúng với n = k, nghĩa là có 1 đỉnh A nối với k – 1 đỉnh còn lại. Ta cm bài toán đúng với n = k + 1.
- Giả sử đỉnh mới thêm vào là đỉnh B. Xét tập hợp 4 đỉnh A, B và 2 đỉnh C, D từ đồ thị.
A đã nối với C và D, nếu A nối với B thì A nối với k đỉnh. Bài toán giải quyết xong. - Nếu A ko nối với B thì C sẽ nối với A, B, D. Cố định C và thay D bằng các đỉnh D1, D2, D3 trong đồ thị. Vì trong tập 4 đỉnh bất kì luôn có 1 đỉnh nối với 3 đỉnh còn lại nên C sẽ nối với các đỉnh A, B, D1, D2,... vậy C là đỉnh nối với k đỉnh còn lại. 2/ Trong giải cờ tướng quốc gia (có 20 kì thủ) hiện đã có 21 trận đấu được tiến hành. CMR có một kì thủ đã thi đấu ít nhất 3 trận.
Solution:
- Cho số kì thủ là là số đỉnh của 1 đồ thị, số trận đấu là số cạnh của đồ thị = m. - Tổng số bậc của các đỉnh = 2*m = 42. Vì có 20 kì thủ nên nếu ko có đỉnh nào có bậc 3 thì chỉ có 2*20 = 40 cạnh (trái giả thiết). Vậy phải có 2 đỉnh bậc 3 ⇒ có ít nhất 2 kì thủ đã thi đấu 3 trận.
Undirected Graph
- The AddEdge command adds one or more edges to an undirected graph. By default, the original graph is changed to a graph containing the specified set of edge(s). Theo default, đồ thị ban đầu sẽ thay đổi thành đồ thị mới chứa tập các cạnh thêm vào. By setting inplace = false the original graph remains unchanged. Bằng thiết lập inplace = false, đồ thị ban đầu sẽ ko thay đổi.
- If the graph is weighted, then a weighted edge can be added by calling AddEdge with one or more edges in the form [edge, weight], where the edge is just the set of two vertices (đỉnh), and the weight represents (đại diện) the value of the edge weight. > with( GraphTheory):
G := CycleGraph(5):
AddEdge( G, {{1, 3}, {2, 4}}, inplace = true); DrawGraph(G);
Graph G: an undirected unweighted graph with 5 vertices and 7 edge(s)
> with( GraphTheory):
G := Graph( Matrix( [ [0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 0], [0, 1, 0, 0] ] ), 'weighted'); Edges( G, weights); DrawGraph(G); 0, 1, 1, 0 1, 0, 0, 1 1, 0, 0, 0 0, 1, 0, 0
Graph G: an undirected weighted graph with 4 vertices and 3 edge(s) [{1, 2}, 1], [{1, 3}, 1], [{2, 4}, 1]
> AddEdge( G, [{1, 4}, 2]); Edges( G, weights); DrawGraph(G); > G := Graph( [a, b, c, d] ); AddEdge( G, Trail( a, b, c, d, a ) ); DrawGraph(G); AdjacencyMatrix(G); 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 Directed Graph 1/ > with( GraphTheory):
DrawGraph(G);
AddArc( G, {[a, c], [b, d]} ); DrawGraph(G);
2/ > with( GraphTheory):
G := Graph( Matrix( [ [0, 1, 1, 0], [1, 0, 0, 3], [0$4] $2] ), 'weighted', 'directed'); DrawGraph(G); 4/ > with( GraphTheory): G := Digraph( [1, 2, 3, 4], Trail( 1, 2, 3, 4, 1) ); DrawGraph(G); AdjacencyMatrix(G); 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
Minimal Spanning Tree GraphTheory [KruskalsAlgorithm] GraphTheory [PrimsAlgorithm] - Calling Sequence: MinimalSpanningTree(G) MinimalSpanningTree(G, w, animate) KruskalsAlgorithm(G, w, animate) PrimsAlgorithm(G, w, animate) Parameters:
G: an undirected graph, weighted or unweighted w: (optional) name
animate: (optional) literal animate (theo nghĩa của ảnh động) indicating (cho biết) that an animation of the algorithm should be returned instead of the tree.
Description
- MinimalSpanningTree, KruskalsAlgorithm, and PrimsAlgorithm all return a spanning tree of the undirected graph G with minimum possible weight. If the graph G is unweighted, each edge is considered to have weight 1.
- If the optional parameter w is given, it is assigned (được gán cho) the weight of the minimal spanning tree.
- If the literal animate, or animate = true is given, an animation of the application of the algorithm will be returned instead of the minimal spanning tree. Nếu có chữ animate or animate = true, 1 ảnh động của thuật toán sẽ cho kết quả thay cho cây khung tối thiểu.
> with( GraphTheory ): with( RandomGraphs ): A := Matrix( [ [0, 1, 0, 4, 0, 0], [1, 0, 1, 0, 4, 0], [0, 1, 0, 3, 0, 1], [4, 0, 3, 0, 1, 0], [0, 4, 0, 1, 0, 4], [0, 0, 1, 0, 4, 0] ]): G := Graph(A): DrawGraph(G);
1 2 3 4 5 6 1 0 1 0 4 0 0 2 1 0 1 0 4 0 3 0 1 0 3 0 1 4 4 0 3 0 1 0 5 0 4 0 1 0 4 6 0 0 1 0 4 0 T := MinimalSpanningTree(G); DrawGraph(T); 1 – 2; 2 – 3; 3 – 4; 3 – 6; 4 – 5; Edges(T, weights); { [{1, 2}, 1], [{2, 3}, 1], [{3, 4}, 3], [{3, 6}, 1], [{4, 5}, 1] } PrimsAlgorithm( G, 'w', animate); w;
KruskalsAlgorithm( G, 'w', animate); w; Dijkstras Algorithm Calling Sequence DijkstrasAlgorithm(G, s, t) DijkstrasAlgorithm(G, s, T) DijkstrasAlgorithm(G, s) Parameters
- G: a graph with nonnegative edge weights or no weights - s, t: vertices of the graph G
- T: list of vertices of the graph G Description
- If G is an unweighted graph, the edges are assumed all to have weight 1. - If G is a weighted graph, DijkstrasAlgorithm(G, s, t) returns the cheapest
weighted path from vertex s to vertex t in the graph G. If a path from s to t exists, the output is a list of the form [[s,...,t], w] where [s,...,t] is the path and w is the weight of that path. If no such path exists the output is .
- In the second calling sequence where T is a list of vertices of G, this is short for [seq(DijkstrasAlgorithm(G, s, t), t = T)], save that the algorithm does not need to recompute cheapest paths.
- In the third calling sequence where no destination vertices (điểm đích) are given, this is short for DijkstrasAlgorithm(G, s, Vertices(G)), i.e. the cheapest path from s to every vertex in G is output.
- To compute distances between all pairs of vertices simultaneously (đồng thời), use the AllPairsDistance command. To ignore edge weights (and use a faster breadth-first search) use the ShortestPath command.
- If some edge weights are negative, the BellmanFordAlgorithm command can be used to compute the shortest path.
> with( GraphTheory ): G := Graph( { [{1, 2}, 1], [{2, 3}, 3], [{3, 4}, 7], [{4, 5}, 8], [{5, 6}, 15], [{1, 6}, 11] } ); DijkstrasAlgorithm( G, 1, 4); DrawGraph(G); WeightMatrix(G) > G := Graph( { [{1, 2}, 1], [{2, 3}, 3], [{3, 4}, 7], [{2, 4}, 2], [{4, 1}, 15] } ); DijkstrasAlgorithm( G, 1, 4); DrawGraph(G); [ [1, 2, 4], 3 ] > WeightMatrix(G) 0 1 0 15 1 0 3 2 0 3 0 7
15 2 7 0 x1[16] = { 0, 1, 0, 15, 1, 0, 3, 2, 0, 3, 0, 7, 15, 2, 7, 0 }; Weight Matrix Calling Sequence WeightMatrix(G, cp) Parameters G: weighted graph
cp: (optional) symbol or equation Description
- WeightMatrix returns the matrix of edge weights of a weighted graph. The optional argument cp is used to control whether the weight matrix of the graph or a copy of it should be returned. The argument cp can be either the symbol copy or an equation of the form copy=true or copy=false. If the argument is missing the
command returns a copy of the weight matrix of the graph by default. The types of Graph
Cho G = (X, E) là đồ thị ko hướng.
a/ G gọi là k-đều nếu d(i) = k, với mọi I thuộc X.
b/ G gọi là lưỡng phân nếu X có thể phân hoạch thành X1, X2 sao cho mọi cạnh của G đều nối 1 đỉnh trong X1 với 1 đỉnh trong X2 và viết là G = (X1, X2, E)
- Nếu G đơn và mỗi đỉnh trong X1 đều nối với tất cả các đỉnh trong X2 thì G gọi là đồ thị lưỡng phân đủ, kí hiệu là K(r, s), với r = số đỉnh của X1 = |X1|, s = số đỉnh của X2 = |X2|. Đặc biệt, K(1, s) gọi là đồ thị 1 ngôi sao.
c/ G gọi là 1 bánh xe nếu G có n – 1 đỉnh và n – 1 cạnh tạo thành 1 đa giác đều, và tất cả các đỉnh đều nối với tâm của đa giác. Kí hiệu Wn.
> with(GraphTheory): with(SpecialGraphs):
G := GeneralizedPetersenGraph(5, 2); DrawGraph(G);
> DegreeSequence(G); with(networks) Vẽ đồ thị K5. > G := CycleGraph(5); DrawGraph(G); AddEdge( G, { {1, 3}, {1, 4}, {2, 4}, {2, 5}, {3, 1}, {3, 5}, {4, 1}, {4, 5} } ); DrawGraph(G); > with(GraphTheory): G := Graph( [1, 2, 3, 4, 5]); for i from 1 to 5 do for j from 1 to 5 do if (i != j) then AddEdge( G, {i, j}); end if; end do;
end do; DrawGraph(G); Đồ thị K5. AdjacencyMatrix(G); 1 2 3 4 5 1 0 1 1 1 1 2 1 0 1 1 1 3 1 1 0 1 1 4 1 1 1 0 1 5 1 1 1 1 0 DijkstrasAlgorithm( G, 1 ); Vẽ đồ thị K6 G := Graph( [1, 2, 3, 4, 5, 6]); DrawGraph(G); for i from 1 to 6 do for j from 1 to 6 do if (i != j) then AddEdge( G, {i, j}); end if; end do; end do; DrawGraph(G);
G := Graph( [1, 2, 3, 4, 5, 6]); for i from 1 to 6 do
for j from 1 to 6 do
if (i != j and j != i+3) then AddEdge( G, {i, j}); end if; end do; end do; DeleteEdge( G, { {1, 4}, {2, 5}, {3, 6} }); DrawGraph(G); AdjacencyMatrix(G); 1 2 3 4 5 6 1 0 1 1 0 1 1 2 1 0 1 1 0 1 3 1 1 0 1 1 0 4 0 1 1 0 1 1
5 1 0 1 1 0 1
6 1 1 0 1 1 0
int *x, n, i, j; n = 6; x = new int [37]; for (i = 1; i <= n; i++) for (j = 1; j <= n; i++) x[i][j] = 1; for (i = 1; i <= 3; i++) for (j = 4; j <= 6; j++) if (j == i+3) x[i][j] = 0; Vẽ đồ thị K(3, 4) G := Graph( [1, 2, 3, 4, 5, 6, 7]); for i from 1 to 3 do for j from 4 to 7 do if (i != j) then AddEdge( G, {i, j}); end if; end do; end do; DrawGraph(G); Vẽ đồ thị W6 G := Graph( [1, 2, 3, 4, 5, 6], Trail(1, 2, 3, 4, 5, 1) ); for i from 1 to 5 do AddEdge( G, {i, 6}); end do;
DrawGraph(G); DijkstrasAlgorithm( G, 1 ); > with(GraphTheory): with(SpecialGraphs): G := GeneralizedPetersenGraph(5, 2); DrawGraph(G); > with(GraphTheory): with(SpecialGraphs): G := GeneralizedPetersenGraph(6, 2); DrawGraph(G);
> with(GraphTheory): with(SpecialGraphs): G := GeneralizedPetersenGraph(7, 2); DrawGraph(G); > with(GraphTheory): with(SpecialGraphs): G := WheelGraph(6); DrawGraph(G);
Prims Algorithm Tìm cây khung có trọng số nhỏ nhất. > with(GraphTheory): G := Graph( { [{1, 2}, 1], [{1, 3}, 1], [{1, 4}, 1], [{1, 5}, 1], [{2, 3}, 1], [{2, 4}, 1], [{2, 5}, 1], [{3, 4}, 1], [{3, 5}, 1], [{4, 5}, 1] } ); DrawGraph(G); PrimsAlgorithm(G); > with(GraphTheory):
G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } ); DrawGraph(G); PrimsAlgorithm(G, 'w', animate); Edge (1, 2): 3 Edge (2, 3): 5 Edge (2, 4): 6 Edge (1, 5): 16 KruskalsAlgorithm(G, 'w', animate); WeightMatrix(G); 1 2 3 4 5 1 0 3 24 35 16 2 3 0 5 6 17 3 24 5 0 7 38 4 35 6 7 0 19
5 16 17 38 19 0
x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }
x1[] = { 0, 3, 24, 35, 16, 3, 0, 5, 6, 17, 24, 5, 0, 7, 38, 35, 6, 7, 0, 19, 16, 17, 38, 19, 0 };
x1[] = { 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0 };
Prim Algorithm code C++ with Notation #include <iostream.h>
#include <stdio.h> class Prim {
int n, k;
int visited[10], min, minicost, A[10][10]; public:
Prim() {
k = 1; // Number of Edges minicost = 0; }
void Read();
void Prims1 (int cost[][10], int n); };
void Prim :: Read() {
n = 5; int i, j, k1; k1 = 0;
int x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }; for (i = 1; i <= n; i++) {
for (j = i+1; j <= n; j++) { A[i][j] = x1[k1]; k1++;
printf ("A[%d][%d] = %d ", i, j, A[i][j]); } printf ("\n");
} Prims1 (A, n); }
void Prim :: Prims1 (int A[][10], int n) { int i, j, a, b, b1[n], b2[n], b3[n], k1; k1 = 0;
for (i = 2; i <= n; i++) visited[i] = 0;
cout << "\n Edges in the spanning tree are: \n"; visited[1] = 1;
while (k < n) {
printf ("k = %d \n", k);
for (i = 1, min = 999; i <= n; i++) for (j = i+1; j <= n; j++)
//printf ("\n i = %d, j = %d \n", i, j); if (A[i][j] > min) {
printf ("if A[%d][%d] = %d > min = %d continue \n", i, j, A[i][j], min); }
else if (A[i][j] < min) {
printf ("if A[%d][%d] = %d < min = %d \n", i, j, A[i][j], min); if (visited[i] == 0) {
printf ("if (visited[%d] == %d) continue \n", i, visited[i]); continue; }
else {
min = A[i][j]; a = i; b = j;
printf ("min = A[%d][%d] = %d \n", i, j, min); //printf ("a = i = %d, b = j = %d \n", i, j);
} }
if (visited[a] == 0 || visited[b] == 0) {
printf ("\n if (visited[a] = visited[%d] == %d) \n", a, visited[a]); printf ("or if (visited[b] = visited[%d] == %d) \n", b, visited[b]); k++; printf ("k++ = %d \n", k);
printf ("Edge(%d, %d): %d \n", a, b, min); b1[k1] = a; b2[k1] = b; b3[k1] = min; k1++; minicost += min; visited[b] = 1;
printf ("visited[b] = visited[%d] = 1 \n", b); } A[a][b] = A[b][a] = 999;
printf ("A[%d][%d] = A[%d][%d] = 999 \n", a, b, b, a); printf ("min = %d \n", min);
} cout << "\n Minimum cost spanning tree is:" << minicost; printf ("The Spanning Tree \n");
for (i = 0; i < n-1; i++)
printf ("Edge (%d, %d): %d \n", b1[i], b2[i], b3[i]); }
int main() {
cout << "\n Prim's algorithm \n"; Prim p; p.Read();
}
Code Maple Prims
Prims := proc(G::Graph, x0)
local n, A, Kt, i, j, t, min, a, b, T;
min := 999; A := WeightMatrix(G); n := NumberOfVertices(G); Kt := {x0}; T := Graph(n);
if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if;
for t from 1 to n-1 do min := 999; for i in Kt do
for j from 1 to n do
min := A(i, j); a := i; b := j; end if; end do; end do; Kt := Kt union {b}; T := AddEdge(T, {a, b}); end do; return T; end proc: with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); T := Prims(G, 1); HighlightEdges(G, T, red); DrawGraph(G); with(GraphTheory): G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } ); DrawGraph(G); C := Edges( G, weights); C = { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } for y in C do
print( y[1][1], y[1][2], y[1], y[2]); end do;
y[1][1] = 1; y[1][2] = 2; y[1] = {1, 2}; y[2] = 3; y[1][1] = 1; y[1][2] = 3; y[1] = {1, 3}; y[2] = 24; for y in C do
if y[1] = {1, 3} then print(y[2]); end if; end do;
y[2] = 24.
if (i[1][1]=x1 and i[1][12] = x2) or (i[1][2]=x1 and i[1][1]=x2) for i in Edges(G,weights)
if( y[1] = {x1, x2} or y[1] = {x2, x1} ) y[1][2] lúc đó chính là trọng lượng
Giải thuật:
- Step 1: Chọn tùy ý đỉnh x0∈X và khởi tạo V :=
{ }
x , T :0 = ∅, V là tập đỉnh, T là tập cạnh.- Step 2: Trong số những cạnh nối đỉnh x0 với y mà x0∈V and y X \ V∈ , ta chọn
cạnh e có trọng số nhỏ nhất. Nếu ko có cạnh e: Dừng (1). - Step 3: Gán V := V ∪ {y}, and T := T ∪ {e}.
- Step 4: Nếu T đủ n-1 phần tử thì Dừng (2), ngược lại làm tiếp bước 2.
Ghi chú: Khi thuật toán dừng theo trường hợp 1 (Tìm ko có cạnh từ x đi ra) thì đồ thị ko liên thông nên ko có cây khung.
> with(GraphTheory):
G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } );
DrawGraph(G);
Prim Algorithm
- Step 1: chọn đỉnh 1, trong số những cạnh kề với đỉnh 1, chọn cạnh {1, 2} có trọng số min là 3.
- Step 2: chọn đỉnh 2, trong số những cạnh kề với đỉnh 1, 2, chọn cạnh {2, 3} có trọng số min là 5.
- Step 3: trong số những cạnh kề với đỉnh 1, 2, 3 chọn cạnh {2, 4} có trọng số min là 6.
- Step 4: trong số những cạnh kề với đỉnh 1, 2, 3, 4 chọn cạnh {3, 4} có trọng số min là 7. {2, 3, 4} tạo thành chu trình nên bỏ cạnh {3, 4}.
- Step 5: trong số những cạnh kề với đỉnh 1, 2, 3, 4, chọn cạnh {1, 5} có trọng số min là 16.
Kruskal Algorithm
- Step 1: chọn cạnh {1, 2} có trọng số min là 3. - Step 2: chọn cạnh {2, 3} có trọng số min là 5.
- Step 3: chọn cạnh {2, 4} có trọng số min là 6.
- Step 4: chọn cạnh {3, 4} có trọng số min là 7. Nhưng {2, 3, 4} tạo thành chu trình nên bỏ cạnh {3, 4}.
- Step 5: chọn cạnh {1, 5} có trọng số min là 16.
Kruskal Algorithm Code C++ 1
Step 1: Sắp xếp các cạnh của đồ thị theo thứ tự trọng số tăng dần và khởi tạo cây T = Ø
Step 2: Duyệt theo cạnh e thuộc danh sách đã sắp xếp. Nếu T + e ko chứa chu trình thì:
Ghép cây e vào cây: T = T + {e}; Nếu T đủ n – 1 phần tử thì dừng. #include <iostream.h> #include <stdio.h> #define MAX 100 class Kruskal { private: struct Edge1 { int u, v, weight; } Edge[MAX];
int Tree[MAX][2], set[MAX]; int n; public:
int ReadEdges(); void MakeSet(); int Find (int vertex); void Join (int v1, int v2); void Arrange (int k); int SpanningTree (int k); void Display (int k); };
int Kruskal :: ReadEdges() {
int i, j, k, m; k = 1; n = 5; m = 0; int x[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }; for (i = 1; i <= n; i++) for (j = i+1; j <= n; j++) { Edge[k].u = i; Edge[k].v = j; Edge[k++].weight = x[m]; m++; } return (k - 1); }
void Kruskal :: MakeSet() { int i;
set[i] = i; }
int Kruskal :: Find (int vertex) { return (set[vertex]);
}
void Kruskal :: Join (int v1, int v2) { int i, j;
if (v1 < v2) {
printf ("if (v1 = %d < v2 = %d) \n", v1, v2); printf ("set [v2] = v1; set[%d] = %d \n", v2, v1); set[v2] = v1; }
else {
printf ("if (v1 = %d > v2 = %d) \n", v1, v2); printf ("set[v1] = v2; set[%d] = %d \n", v1, v2); set[v1] = v2; }
}
void Kruskal :: Arrange (int k) { int i, j;
struct Edge1 temp; for (i = 1; i < k; i++)
for (j = 1; j <= k - i; j++)
if (Edge[j].weight > Edge[j + 1].weight) { temp = Edge[j];
Edge[j] = Edge[j + 1]; Edge[j + 1] = temp; }
}
int Kruskal :: SpanningTree (int k) {
int i, t, j, sum, k1, k2; Arrange(k); t = 1; sum = 0; for (i = 1; i <= k; i++)
printf ("Edge (%d, %d): %d \n", Edge[i].u, Edge[i].v, Edge[i].weight); for (i = 1; i <= n; i++)
if (Find (Edge[i].u) != Find (Edge[i].v)) { for (j = 1; j <= n; j++)
printf ("set[%d] = %d ", j, set[j]); k1 = Edge[i].u; k2 = Edge[i].v;
printf ("\n if (Find (Edge[%d].u) != Find (Edge[%d].v)) \n", i, i); printf (" Find(%d) = set [%d] = %d \n", k1, k1, set[k1]);
printf (" Find(%d) = set [%d] = %d \n", k2, k2, set[k2]); Tree[t][1] = Edge[i].u;
Tree[t][2] = Edge[i].v;
printf ("Tree[%d][1] = Edge[%d].u = %d \n", t, i, Edge[i].u); printf ("Tree[%d][1] = Edge[%d].v = %d \n", t, i, Edge[i].v); sum += Edge[i].weight;
Join (Edge[t].u, Edge[t].v); t++; }
else {
printf ("if (Find (Edge[%d].u) == Find (Edge[%d].v)) continue \n", i, i); printf ("Edge[%d].u = %d, Edge[%d].v = %d \n", i, Edge[i].u, i, Edge[i].v); continue; }
return sum; }
void Kruskal :: Display (int k) { int i;
cout << "\n The Edges of the Minimum Spanning Tree are \n "; for (i = 1; i < n; i++)
cout << Tree[i][1] << " - " << Tree[i][2] << endl;
cout << "\n The Cost of the Minimum Spanning Tree is : " << k; }
int main() {
int ecount, totalcost; Kruskal k;
ecount = k.ReadEdges(); k.MakeSet(); totalcost = k.SpanningTree (ecount); k.Display (totalcost);
return 0; }
Kruskal Algorithm Code C++ 2 #include <iostream.h>
#include <stdio.h> class Kruskal { private:
int n; // number of nodes
int noe; //no edges in the graph int graph [100][4]; int sets[10]; int k2; public: void ReadGraph(); void Initial(); void SortEdges(); void Algorithm(); int FindNode(int k); void print(); };
void Kruskal :: ReadGraph() {
int x[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }; for (i = 1; i <= n; i++) {
for (j = i+1; j <= n; j++) { if (x[k] != 0) {
noe++; graph [noe][1] = i;
graph [noe][2] = j; graph [noe][3] = x[k]; k++; } } }
// print the graph edges
cout << "\n The edges in the given graph are:: \n"; for (i = 1; i <= noe; i++)
cout << " < " << graph [i][1] << " , " << graph [i][2] << " > ::" << graph [i][3] << endl;
}
void Kruskal :: SortEdges() {
/* Sort the edges using bubble sort in increasing order */ int i, j;
for (i = 1; i <= noe-1; i++) { for (j = 1; j <= noe-i; j++) { if (graph [j][3] > graph [j+1][3]) { int t = graph [j][1]; graph [j][1] = graph [j+1][1]; graph [j+1][1] = t; t = graph [j][2]; graph [j][2] = graph [j+1][2]; graph [j+1][2] = t; t = graph [j][3]; graph [j][3] = graph [j+1][3]; graph [j+1][3] = t; } } }
// print the graph edges
cout << "\n After sorting the edges in the given graph are:: \n"; for (i = 1; i <= noe; i++)
cout << " < " << graph [i][1] << " , " << graph [i][2] << " > ::" << graph [i][3] << endl;
}
void Kruskal :: Algorithm() { int i, j, k1, p1, p2; k2 = 1; // ->make a set for each node for (i = 1; i <= n; i++) {
sets[i] = i;
} cout << "\n The algorithm starts :: \n"; for (i = 1; i <= n; i++) {
printf ("p1 = FindNode (graph[%d][1] = %d) \n", i, graph [i][1]); p1 = FindNode (graph [i][1]);
printf ("p1 = %d \n", p1);
printf ("p2 = FindNode (graph[%d][2] = %d) \n", i, graph [i][2]); p2 = FindNode (graph [i][2]);
printf ("p2 = %d \n", p2); if (p1 != p2) {
cout << "The edge included in the tree is :: " << " < " << graph [i][1] << " , "
<< graph [i][2] << " > " << endl; k2++;
} /* End if (p1 != p2) */ else {
cout << "Inclusion of the edge " << " < " << graph [i][1] << " , " << graph [i][2] << " > " << "forms a cycle so it is removed \n"; }
} /* End for (i = 1; i <= noe; i++) */ }
int Kruskal :: FindNode (int n) { for (int i = 1; i <= k2; i++) {
if (n == sets[i]) {
printf ("if (%d == sets[%d] = %d) \n", n, i, sets[i]); printf ("return 1 \n");
return 1; }
else {
printf ("if (%d != sets[%d] = %d) \n", n, i, sets[i]); printf ("return -1 \n");
}
} return -1; }
int main() {
Kruskal obj; obj.ReadGraph(); obj.SortEdges(); obj.Algorithm(); return 0;
}
Code Maple Kruskal with(GraphTheory):
G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } );
DrawGraph(G);
Kruskal := proc(G::Graph)
local n, A, i, j, k, t, min, il, jl, T, Mien, tam; min := 999;
A := WeightMatrix(G); n := NumberOfVertices(G); Mien := array(1..n): T := Graph(n);
return ("Do thi nay ko lien thong"); end if; for i from 1 to n do Mien[i] := i; end do; for t from 1 to n-1 do min := 999; for i from 1 to n-1 do for j from 1 to n do
if 0 < A[i, j] < min and Mien[i] != Mien[j] then min := A[i, j]; il := i; jl := j; end if; end do; end do; T := AddEdge(T, {il, jl} ); Mien[jl] := Mien[il]; end do; return T; end proc: with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); T := Kruskal(G, 1);
HighlightEdges(G, T, red); DrawGraph(G);
Code 2:
Kruskal := proc(G::Graph)
local n, A, i, j, k, t, min, il, jl, T, Mien, tam, Kt; min := 999; Kt := { };
A := WeightMatrix(G); n := NumberOfVertices(G); Mien := array(1..n): T := Graph();
if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if; for i from 1 to n do Mien[i] := i; end do; for t from 1 to n-1 do min := 999; for i from 1 to n do for j from 1 to n do
min := A[i, j]; il := i; jl := j; end if;
end do; end do;
if il ∉ Kt then T := AddVertex(T, il); Kt := Kt union {il}; end if; if jl ∉ Kt then T := AddVertex(T, jl); Kt := Kt union {jl}; end if; T := AddEdge(T, {il, jl} ); Mien[jl] := Mien[il]; end do; return T; end proc: with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); T := Kruskal(G, 1);
HighlightEdges(G, T, red); DrawGraph(G);
Depth First Search #include <iostream.h> #include <stdio.h> #include <conio.h> #include <string.h> #define MAX 20 int A[MAX][MAX]; int v[MAX]; int i = 1, n; int T[20]; void DFS (int v1) { int v2; cout << v1 << "\t"; v[v1] = 1; printf ("v[%d] = 1 \n", v1); for (v2 = 1; v2 <= n; v2++) if (A[v1][v2] != 0 && v[v2] == 0) {
printf ("if (A[%d][%d] == 1 && v[%d] == 0) \n", v1, v2, v2); printf ("%d - %d \n", v1 , v2); printf ("DFS (%d) \n", v2); T[i] = v1; T[i+1] = v2; i = i + 2; DFS (v2); } } void Create() { n = 9; int i, j, k1; k1 = 0;
int x1[] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; for (i = 1; i <= n; i++) for (j = i+1; j <= n; j++) { A[j][i] = A[i][j] = x1[k1]; k1++; } for (i = 1; i <= n; i++) { j = i; A[i][j] = 0; } for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { cout.width(5); cout << A[i][j]; } printf ("\n"); } } int main() { int i, v1, v2; Create(); for (v1 = 1; v1 <= n; v1++) v[v1] = 0; DFS (1); for (i = 1; i < 2*n-1; i += 2)
printf ("%d - %d \n", T[i], T[i+1]); return 0; } Code Maple DFS with(GraphTheory): G := Graph( [1, 2, 3, 4, 5, 6, 7, 8, 9]); AddEdge( G, { {1, 2}, {1, 3}, {2, 4}, {2, 5}, {2, 6}, {3, 7}, {3, 8}, {3, 9} }); DrawGraph(G); DFS := proc(k::integer) local i; global Kt, A, n, E; Kt := Kt union {k}; for i from 1 to n do
if A(k, i) != 0 and i ∉ Kt then
E := AddEdge(E, {k, i} ); DFS(i); end if; end do; end proc: main := proc(G::Graph, k) global n, A, E, Kt;
n := NumberOfVertices(G); A := AdjacencyMatrix(G); E := Graph(n); Kt := { };
if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if; DFS(k); return E; end proc: with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); T := main(G, 2);
HighlightEdges(G, T, red); DrawGraph(G);
Tạo 1 mảng có 10 phần tử = 0 trong Maple: V := [ seq( 0, i = 1..10) ];
V := array(1..n) for i from 1 to n do
V[i] := 0; end do;
Depth First Search Algorithm
- Given graph G = (X, E), X is the set of vertices, E is the set of edges.
- Step 1: Sorting the vertices by order: x1, x2, x3... Choose arbitrary vertex x = x1, A = X – {x1} (remove x1 out of set of vertices). Initialize set of edges T = Ø.
- Step 2: If N(x) (set of vertices near x) intersect with A = Ø, so going to Step 4. If N(x) intersect with A ≠ Ø, so going to Step 3.
- Step 3: Choose min i so that xi in N(x) intersect with A,
and choosing e = {x, xi}. T = T + e, A = A – xi, x = xi. Return Step 2. - Step 4: If x = x1 then stopping. T is the Tree.
1 2 3 4 5 6 7 8 9 1 0 1 1 0 0 0 0 0 0 2 0 0 1 1 1 0 0 0 3 0 0 0 0 1 1 1 4 0 0 0 0 0 0 5 0 0 0 0 0 6 0 0 0 0 7 0 0 0 8 0 0 9 0 int x1[] = { 1, 1, 0, 0, 0, 0, 0, 0,/ 0, 1, 1, 1, 0, 0, 0,/ 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,/ 0, 0, 0, 0,/ 0, 0, 0,/ 0, 0,/ 0}; int x1[] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- Step 1: Khởi tạo mảng v[9] = {0}. Chọn x1 là phần tử bắt đầu, v[1] = 1, đánh dấu phần tử x1. Bỏ x1 khỏi A: A = { x2, x3, x4, x5, x6, x7, x8, x9}
- Step 2: If (v[2] == 0 && A[1][2] != 0), chọn x2 là phần tử nhỏ nhất kề với x1, x = x2. Thêm vào T cạnh {x1, x2}. v[2] = 1, bỏ x2 khỏi A: A = { x3, x4, x5, x6, x7, x8, x9}
- Step 2: If (v[4] == 0 && A[2][4] != 0), chọn x4 là phần tử nhỏ nhất kề với x2, x = x4. Thêm vào T cạnh {x2, x4}. v[4] = 1, bỏ x4 khỏi A: A = { x3, x5, x6, x7, x8, x9}
- Step 3: Vì giao các đỉnh kề của x4 với A = Ø nên dò ngược pre(x4) = x2.
- Step 2: If (v[5] == 0 && A[2][5] != 0), chọn x5 là phần tử kế tiếp kề với x2, x = x5. Thêm vào T cạnh {x2, x5}. v[5] = 1, bỏ x5 khỏi A: A = { x3, x6, x7, x8, x9 }
- Step 3: Vì giao các đỉnh kề của x5 với A = Ø nên dò ngược pre(x5) = x2.
- Step 2: If (v[6] == 0 && A[2][6] != 0), chọn x6 là phần tử kế tiếp kề với x2, x = x6. Thêm vào T cạnh {x2, x6}. v[6] = 1, bỏ x6 khỏi A: A = { x3, x7, x8, x9 }
- Step 3: Vì giao các đỉnh kề của x6 với A = Ø nên dò ngược pre(x6) = x2. Vì giao các đỉnh kề của x2 với A = Ø nên dò ngược pre(x2) = x1.
- Step 2: If (v[3] == 0 && A[1][3] != 0), chọn x3 là phần tử kế tiếp kề với x1, x = x3. Thêm vào T cạnh {x1, x3}. v[3] = 1, bỏ x3 khỏi A: A = { x7, x8, x9 }
T = { {x1, x2}, {x2, x4}, {x2, x5}, {x2, x6}, {x1, x3}, {x3, x7}, {x3, x8}, {x3, x9} }
Breadth First Search Algorithm
- Given graph G = (X, E), X is the set of vertices, E is the set of edges.
- Step 1: Sorting the vertices by order: x1, x2, x3... Choose arbitrary vertex x = x1, A = {x1}, B = X – {x1} (remove x1 out of set of vertices). Initialize set of edges T = Ø. N(x) is the set of vertices near x.
- Step 2: If B = Ø then stopping. T is the tree. If B ≠ Ø then going to Step 3 where S = Ø.
- Step 3: Put x = minA. If N(x) intersect with B = Ø then going Step 4.
If N(x) intersect with B = { y1,..., yk } then choosing the edges e = xyj and T = T + e1 +... ek, B = B – { y1,..., yk }.
S = S + { y1,..., yk }
- Step 4: A = A – {x}. If A is different Null, then returning Step 2. If A is Null, then returning Step 3 with A = S.
- Step 1: Khởi tạo mảng v1[9] = {0}. Chọn x1 là phần tử bắt đầu, v1[1] = 1, v1[] là mảng đánh dấu phần tử x1 của B. Bỏ x1 khỏi B: B = { x2, x3, x4, x5, x6, x7, x8, x9 }, v[1] = 1, A = {x1}. v2[9] = {0}, v2[] là mảng đánh dấu phần tử của S.
T = Ø, S = Ø.
- Step 2: If B ≠ Ø then going to Step 3 with S = Ø. B ≠ Ø: for (i = 0; i < n; i++) if (v1[i] == 0) S = Ø: for (i = 0; i < n; i++) v2[i] = 0;
T = T + {x1, x2} + {x1, x3}; v[2] = v[3] = 1;
B = B – {x2, x3} = { x4, x5, x6, x7, x8, x9 }; S = S + {x2, x3} = {x2, x3}. - Step 4: A = A – {x1} = Null; returning Step 2 with A = S.
- Step 2: If B ≠ Ø then going to Step 3 with S = Ø.
- Step 3: Put x = minA = x2, N(x) intersect with B = { x4, x5, x6 }. T = T + {x2, x4} + {x2, x5} + {x2, x6}; v[4] = v[5] = v[6] = 1; B = B – { x4, x5, x6 } = { x7, x8, x9 }; S = { x4, x5, x6 }.
- Step 4: A = A – {x2} = {x3}; returning Step 3.
- Step 3: Put x = minA = x3, N(x) intersect with B = { x7, x8, x9 }. T = T + {x3, x7} + {x3, x8} + {x3, x9}; v[7] = v[8] = v[9] = 1; B = B – { x7, x8, x9 } = Null. S = { x7, x8, x9 }.
- Step 4: A = A – {x3} = Null; returning Step 2.
- Step 2: If B = Null then stopping algorithm. T is the Tree.
T = { {x1, x2}, {x1, x3}, {x2, x4}, {x2, x5}, {x2, x6}, {x3, x7}, {x3, x8}, {x3, x9} } BFS Code Maple with(GraphTheory): G := Graph( [1, 2, 3, 4, 5, 6, 7, 8, 9]); AddEdge( G, { {1, 2}, {1, 3}, {2, 4}, {2, 5}, {2, 6}, {3, 7}, {3, 8}, {3, 9} }); DrawGraph(G); BFS := proc( G::Graph, x1) local A, B, C, S, T, x, y, n; A := {x1}; n := NumberOfVertices(G); T := Graph(n); B := { op(Vertices(G)) }; B := B minus {x1}; S := { }; if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if;
while not (B = { }) do x := A[1];
C := { op(Neighbors(G, x) ) } intersect B; B := B minus C; for y in C do
T := AddEdge( T, {x, y}); end do; S := S union C; A := A minus {x}; if A = { } then A := A union S; end if; S := { }; C := { }; end do; return T; end proc: with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); T := BFS(G, 2);
HighlightEdges(G, T, red); DrawGraph(G); BFS Code C++ #include <iostream.h> class Queue { private: int data; Queue *Next; public:
void Enque (int data); int Deque();
} *Head, *Tail;
void Queue :: Enque (int data) { Queue *temp; temp = new Queue;
temp->data = data; temp->Next=NULL; if (Head == NULL) Head = temp; else Tail->Next = temp; Tail = temp; }
int Queue :: Deque() {
Queue* temp; temp = Head; Head = Head->Next; return temp->data; } int visit[100]; int bfs_span_tree[100][100]; class Graph { private: int a; Graph *Next; public: void BFS();
Graph* Create (Graph* Head, int *x, int n); void Ftraverse (Graph *Head);
};
Graph* Graph :: Create (Graph *Head, int *x, int n) { int a, i, k; k = 0; Graph *last; Head = last = NULL; Graph *temp;
for (i = 0; i < n; i++) {
temp = new Graph; temp->a = x[i]; temp->Next = NULL;
if (Head == NULL) Head = temp; else last->Next = temp; last = temp; } return Head; }
void Graph :: Ftraverse (Graph *h) { while (h != NULL) { cout << h->a << "->"; h = h->Next; } cout << "NULL \n"; } void Graph :: BFS() {
cout << "This program is to implement BFS for an unweighted graph \n"; Graph *ptr[100]; int n, i; n = 2;
int x1[9] = { 1, 2, 4, 6, 7, 3, 5, 1, 6 }; int x2[9] = { 4, 7, 3, 5, 1, 2, 5, 7, 4};
ptr[1] = Create (ptr[1], x1, 9); ptr[2] = Create (ptr[2], x2, 9); cout << "\n The Entered Graph is ::\n";
for (i = 1; i <= n; i++) {
cout << "< " << i << " > ::"; Ftraverse (ptr[i]); } int x;
cout << "\n Enter the start node " << n << ">:"; cin >> x; cout << "\n The Breadth first search traversal is: \n"; Queue object;
// Mark all the nodes as not viseted for (i = 1; i <= n; i++)
visit[i] = 0;
for (i = 1; i <= n; i++) for (int j = 1; j <= n; j++)
bfs_span_tree[i][j] = 0; // Enque the start node object.Enque (x); int p;
while (Head != NULL && Tail != NULL) { // Deque a node
p = object.Deque(); int x = p;
// If p is not visited yet. while (ptr[p] != NULL) {
if (visit [ptr [p]->a] != 1) {
// Mark the node as visited. visit [ptr [p]->a] = 1;
bfs_span_tree [ptr [p]->a] [x] = 1; }
// Enque all its adjacent nodes. object.Enque (ptr[p]->a);
ptr[p] = ptr[p]->Next; } }
cout << "\n The required bfs spanning tree is ::\n"; for (i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) cout << bfs_span_tree[i][j] << ' '; cout << "\n"; } cout << "\n"; } int main() { Graph obj; obj.BFS(); return 0; } Dijkstra Algorithm - Cho đồ thị G = (X, E) với các cạnh có trọng số ko âm.
- Dữ liệu nhập cho thuật toán là ma trận trọng số L và 2 đỉnh x, y cho trước. (với quy ước L(x, y) = 999 nếu ko có cạnh nối từ đỉnh x đến đỉnh y).
- Dữ liệu xuất là đường đi ngắn nhất từ x đến y.
Step 1: Assign (gán) T = X, the set of vertices (các đỉnh) of graph.
Initial (khởi động): length[x] = 0; with every k in X \{x}, length[k] = 999. last[k] = 0; mark[k] = 0.
- length[k] is the length of path from vertex x to vertex k. last[] is the array to save the path element. mark[] is the array to mark the elements whether is visited or not. Step 2: If y not in T, Stop.
Choose vertex v in T so that length[v] is min and remove v out of T. mark[v] = 1. Step 3:
With every vertex k in T, and there exist an edge from v to k. If length[k] > length[v] + L(v, k) // weight of edge from v to k.
length[k] = length[v] + L(v, k) last[k] = v.
Continuos step 2. Code Dijkstra Algorithm
#include <iostream.h> #include <stdio.h> class Dijkstra {
private:
int graph[15][15];
int last[15], mark[15], length[15]; int source;
int n; // num_of_vertices public:
int Minimum(); int Read();
void Initialize (int source); void Printpath (int i);
void Algorithm (int source); void Output();
};
int Dijkstra::Read() { n = 5; int i, j, k = 0;
int x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19}; cout << "enter the adjacent matrix: \n"; for (i = 1; i <= n; i++) for (j = i+1; j <= n; j++) { graph[j][i] = graph[i][j] = x1[k]; k++; } for (i = 1; i <= n; i++) graph[i][i] = 0; for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) printf ("%d ", graph[i][j]); printf ("\n"); }
cout << "\n enter the source vertex \n"; cin >> source;
return source; }
void Dijkstra::Initialize (int source) { int i; for (i = 1; i <= n; i++) { mark[i] = 0; length[i] = 999; last[i] = 0; } length [source] = 0; }
Initialize (source); int count = 0, i, u; while (count < n) {
u = Minimum();
printf ("u = Minimum() = %d \n", u); count++; mark[u] = 1;
printf ("mark[%d] = 1 \n", u); for (i = 1; i <= n; i++)
if (graph[u][i] > 0) { if (mark[i] != 1) {
printf ("if (mark[%d] != 1) \n", i);
if (length[i] > length[u] + graph[u][i]) {
printf ("if (length[%d] > length[%d] + graph[%d][%d]) \n", i, u, u, i); printf ("length[%d] = %d, length[%d] = %d \n", i, length[i], u,
length[u]);
printf ("graph[%d][%d] = %d \n", u, i, graph[u][i]); length[i] = length[u] + graph[u][i];
last[i] = u;
printf ("length[%d] = length[%d] + graph[%d][%d] = %d \n", i, u, u, i, length[i]);
printf ("last[%d] = %d \n", i, u); }
} } /* End if (graph[u][i] > 0) */ } }
void Dijkstra::Printpath (int i) { cout << endl;
if (i == source) cout << source; else if (last[i] == 0)
cout << "no path from " << source << " to " << i; else { Printpath (last[i]); cout << "..." <<i; } } void Dijkstra::Output() { int i; for (i = 1; i <= n; i++) { Printpath(i); if (length[i] != 999) cout << "->(" << length[i] << ") \n"; } cout << endl; } int Dijkstra::Minimum() { int min = 999; int i, t; for (i = 1; i <= n; i++) {
if (min >= length[i]) { min = length[i]; t = i; } } } return t; } int main() {
int source; Dijkstra s; source = s.Read(); s.Algorithm (source); s.Printpath(4); return 0;
}
Code Maple Dijsktra
with(GraphTheory): with(RandomGraphs): with(LinearAlgebra):
Dijsktra := proc()
global m, n, DoDai, Browse, Kt; local i, v, min;
while Kt != ∅ do min := 999; v := 0; for i in Kt do
if min >= DoDai[i] then min := DoDai[i]; v := i; end if; end do;
Kt := Kt minus {v}; for i in Kt do
if A[i, v] > 0 and DoDai[i] > DoDai[v] + A[i, v] then DoDai[i] := DoDai[v] + A[i, v];
Browse[i] := v; end if; end do; end do; end proc: ve := proc(x0) local i, E; E := Digraph(n); for i from 1 to n do
if Truoc[i] != i then E := AddArc(E, { [Browse[i], i] }); end if; end do;
print(E);
HighlightEdges(G, E, red); HightlightVertex(G, x0, red); print( DrawGraph(E) );
khoitao := proc(G::Graph, x0)
global m, n, DoDai, Browse, Kt, A; local i, j;
A := WeightMatrix(G); n := NumberOfVertices(G); Kt := { }; Browse := array(1..n); DoDai := array(1..n); if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if; for i from 1 to n do Kt := Kt union {i}; Browse[i] := i; DoDai[i] := 999; end do; for i from 1 to n do for j from 1 to n do
if A[i, j] = 0 then A[i, j] := 999; end if; end do; end do;
DoDai[x0] := 0;
HighlightVertex(G, x0, red); end proc:
with(GraphTheory): with(RandomGraphs):
G := RandomGraph( 8, 10, connected, weights = 1..10); khoitao(G, 1)
Dijsktra(); ve(1);
Dijkstra Algorithm run by hand > with(GraphTheory):
G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } );
WeightMatrix(G); 1 2 3 4 5 1 0 3 24 35 16 2 3 0 5 6 17 3 24 5 0 7 38 4 35 6 7 0 19 5 16 17 38 19 0 int x1[] = { 0, 3, 24, 35, 16, 3, 0, 5, 6, 17, 24, 5, 0, 7, 38, 35, 6, 7, 0, 19, 16, 17, 38, 19, 0 }; int x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19}; DijkstrasAlgorithm( G, 1, 4 ); [ [1, 2, 3, 4], 15] Tìm đường đi ngắn nhất từ đỉnh 1 đến đỉnh 4;
Step 1: Assign T = X\{x}, the set of vertices of graph.
Initial (khởi động): length[1] = 0; with every k in X \{x}, length[k] = 999. last[k] = 0; mark[k] = 0.
- length[k] is the length of path from vertex x to vertex k. last[] is the array to save the path element. mark[] is the array to mark the elements whether is visited or not. Step 2: If y not in T, Stop.
Choose vertex v in T so that length[v] is min and remove v out of T. mark[v] = 1. Step 3:
With every vertex k in T, and there exist an edge from v to k. If length[k] > length[v] + L(v, k) // weight of edge from v to k.
length[k] = length[v] + L(v, k) last[k] = v.
Step 2: Choose v = 1, length[1] = 0 is min; mark[1] = 1; T = { 2, 3, 4, 5 }; Step 3: The vertices k in T that there exist and edge from 1 to k: 2, 3, 4, 5.
for (i = 1; i <= 5; i++) If (mark[2] != 1) {
If (length[2] > length[v] + L(v, k) ) {
// length[2] = 999; length[v] = length[1] = 0; L(v, k) = L(1, 2) = 3; length[2] = length[1] + L(1, 2) = 3; last[2] = 1; } } if (mark[3] != 1) if (length[3] > length[1] + L(1, 3) ) // length[3] = 999; length[1] = 0; L(1, 3) = 24; length[3] = length[1] + L(1, 3) = 24; last[3] = 1; } if (mark[4] != 1) { if (length[4] > length[1] + L(1, 4) ) { // length[4] = 999; length[1] = 0; L(1, 4) = 35; length[4] = length[1] + L(1, 4) = 35; last[4] = 1; } } if (mark[5] != 1) { if (length[5] > length[1] + L(1, 5) ) { // length[5] = 999; length[1] = 0; L(1, 5) = 16; length[5] = length[1] + L(1, 5) = 16; last[5] = 1; } }
Step 2: Choose v = 2, length[2] = 3 is min; mark[2] = 1; T = { 3, 4, 5 }; Step 3: The vertices k in T that there exist and edge from 2 to k: 3, 4, 5.
for (i = 1; i <= 5; i++) If (mark[3] != 1) If (length[3] > length[2] + L(2, 3) ) // length[3] = 24; length[2] = 3; L(2, 3) = 5; length[3] = length[1] + L(2, 3) = 8; last[3] = 2; } If (mark[4] != 1) { If (length[4] > length[2] + L(2, 4) ) { // length[4] = 35; length[2] = 3; L(2, 4) = 6; length[4] = length[2] + L(2, 4) = 9; last[4] = 2; } } If (mark[5] != 1) {
If (length[5] < length[2] + L(2, 5) ) {
// length[5] = 16; length[2] = 3; L(2, 5) = 17; Stop; }
}
Step 2: Choose v = 3, length[3] = 8 is min; mark[3] = 1; T = { 4, 5 }; Step 3: The vertices k in T that there exist and edge from 3 to k: 4, 5.
for (i = 1; i <= 5; i++) If (mark[4] != 1) { If (length[4] < length[3] + L(3, 4) ) // length[4] = 9; length[3] = 8; L(3, 4) = 7; Stop; } } If (mark[5] != 1) { If (length[5] < length[3] + L(3, 5) ) { // length[5] = 16; length[3] = 8; L(3, 5) = 38; Stop; } }
Step 2: Choose v = 4, length[4] = 9 is min; mark[4] = 1; T = { 5 }; Step 3: The vertices k in T that there exist and edge from 4 to k: 5.
for (i = 1; i <= 5; i++) If (mark[5] != 1) { If (length[5] < length[4] + L(4, 5) ) { // length[5] = 16; length[4] = 9; L(4, 5) = 19; Stop; } }
Step 2: If v = 4 == y is not in T. Stop; The path:
void Dijkstra::Printpath (int i) { cout << endl;
if (i == source) cout << source; else if (last[i] == 0)
cout << "no path from " << source << " to " << i; else { Printpath (last[i]); cout << "..." << i; } } Printpath(4); if (last[4] = 2 != 0) Printpath(2); if (last[2] = 1 != 0) Printpath(1); if (i = 1 == source) cout << "..." << i;
1 → 2 → 4.
Bellman-Ford Algorithm
- Step 1: Initialize: P[0][x] = 0; P[0][i] = 9999, with every i ≠ x, k = 1. - Step 2: With every vertex i in X, we calculate:
P[k][i] = min ( { P[k-1][i] }, { P[k-1][j] + L[i][j] ). There exists path from i to j. L[i][j] is the weight matrix.
- Step 3: If row k and row k-1 of matrix P are equal then P[k][i] is the length of shortest path from x to i.
If row k and row k-1 of matrix P are different
If k < n then increasing k = k + 1 and returning Step 2. If k == n then stopping cause graph have negative path.
#include <iostream.h> #include <stdio.h> #include <stdlib.h> #define MAX 20 class bell_ford { private:
int n; int graph[MAX][MAX]; int start; int distance[MAX]; int pre[MAX]; public: void read_graph(); void initialize(); void update(); void check(); void algorithm(); }; void bell_ford::read_graph() { int i, j, k; n = 5; k = 0; int x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }; for (i = 1; i <= n; i++) for (j = i+1; j <= n; j++) { graph[j][i] = graph[i][j] = x1[k]; k++; } for (i = 1; i <= n; i++) graph[i][i] = 0; for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { printf ("%d ", graph[i][j]); } printf ("\n"); }
cin >> start; } void bell_ford::initialize() { int i; for (i = 1; i <= 5; i++) { distance[i] = 9999; pre[i] = 0; } distance[start] = 0; } void bell_ford::update() { int i, u, v; printf ("update \n"); for (u = 1; u <= n; u++) for (v = 1; v <= n; v++) if (graph[u][v] != 0) {
if (distance[v] > distance[u] + graph[u][v]) {
printf ("\n if (distance[%d] > distance[%d] + graph[%d][%d] ) \n", v, u, u, v);
printf ("distance[%d] = %d, distance[%d] = %d \n", v, distance[v], u, distance[u]);
printf ("graph[%d][%d] = %d \n", u, v, graph[u][v]); distance[v] = distance[u] + graph[u][v];
printf ("distance[%d] = distance[%d] + graph[%d][%d] = %d \n", v, u, u, v, distance[v]);
pre[v] = u;
printf ("pre[%d] = %d \n", v, u); }
else {
printf ("\n if (distance[%d] < distance[%d] + graph[%d][%d] ) \n", v, u, u, v);
printf ("distance[%d] = %d, distance[%d] = %d \n", v, distance[v], u, distance[u]);
printf ("graph[%d][%d] = %d \n", u, v, graph[u][v]); printf ("continue \n"); } } } void bell_ford::check () { int i, j, u, v;
printf ("Check Function \n"); for (u = 1; u <= n; u++) for (v = 1; v <= n; v++) {
if (graph[u][v] != 0) {
if (distance[v] > distance[u] + graph[u][v]) { cout << "does not exist's ";
return; } } }
cout << "\n\n There is no negative weight cycle and \n"; cout << "The final paths and the distances are \n";
for (i = 1; i <= n; i++) {
cout << "path for node " << i << " is ::\n"; int arr[MAX], k = 1; j = i;
while (pre[j] != 0) {
printf ("while pre[%d] != 0 \n", j); arr[k] = pre[j]; k++;
printf ("arr[%d] = pre[%d] = %d \n", k-1, j, arr[k-1]); printf ("j = pre[%d] = %d, k = %d \n", j, pre[j], k); j = pre[j];
}
for (k = k - 1; k > 0; k--)
printf ("arr[%d] = %d -> ", k, arr[k]); cout << i << endl;
cout << "distance is " << distance[i] << endl << endl; } } void bell_ford::algorithm() { read_graph(); initialize(); update(); check(); } int main() { bell_ford obj; obj.algorithm(); } BellmanFord Code 2. #include <stdio.h> #include <stdlib.h> #include <iostream.h> struct Edge{ int source; int dest; int weight; };
void BellmanFord (Edge edges[], int edgecount, int nodecount, int source) { int *d = new int [nodecount + 1];
int i, j, k1, k2, k3, d1;
for (i = 0; i <= nodecount; i++) d[i] = 9999;
d[source] = 0;
for (i = 0; i < edgecount; i++) {
k1 = edges[i].source; k2 = d[edges[i].source]; k3 = edges[i].dest; if (d[edges[i].source] != 9999) { printf ("\n if (d[%d] = %d != 9999) \n", k1, k2); d1 = d[edges[i].source] + edges[i].weight; printf ("d1 = d[%d] + edges[%d].weight = %d \n", k1, i, d1); printf ("edges[%d].source = %d \n", i, k1); printf ("edges[%d].dest = %d \n", i, k3);
printf ("edges[%d].weight = %d \n", i, edges[i].weight); if (d1 < d[edges[i].dest]) { printf ("if (d1 = %d < d[%d] = %d) \n", d1, k3, d[k3]); d[edges[i].dest] = d1; printf ("d[%d] = %d \n", k3, d1); } else { printf ("if (d1 = %d > d[%d] = %d) \n", d1, k3, d[k3]); printf ("continue \n"); } } }
for (i = 0; i < edgecount; i++)
if (d[edges[i].dest] > d[edges[i].source] + edges[i].weight) { printf ("Negative edge weight cycles detected!");
free(d); return; }
for (i = 1; i <= nodecount; i++) {
printf ("The shortest distance between nodes %d and %d is %d \n", source, i, d[i]); } free(d); return; } int main() { Edge edges[10] = { {1, 2, 3}, {1, 3, 24}, {1, 4, 35}, {1, 5, 16}, {2, 3, 5}, {2, 4, 6}, {2, 5, 17}, {3, 4, 7}, {3, 5, 38}, {4, 5, 19} }; BellmanFord (edges, 10, 5, 1); return 0; }
Bellman-Ford run by hand > with(GraphTheory):
G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } ); DrawGraph(G); BellmanFordAlgorithm( G, 1, 4); Edge edges[10] = { {1, 2, 3}, {1, 3, 24}, {1, 4, 35}, {1, 5, 16}, {2, 3, 5}, {2, 4, 6}, {2, 5, 17}, {3, 4, 7}, {3, 5, 38}, {4, 5, 19} };
- Step 1: Initialize distance[i] = 9999 with every i ≠ 1.
distance [1] = 0; pre[i] = 0 with every i in X (set of vertices). - Step 2:
for (u = 1; u <= n; u++) for (v = 1; v <= n; v++) if (graph[1][2] == 3 != 0)
if (distance[2] > distance[1] + graph[1][2])
distance[2] = 9999; distance[1] = 0; graph[1][2] = 3; distance[2] = distance[1] + graph[1][2] = 3.
pre[2] = 1;
if (graph[1][3] == 24 != 0)
if (distance[3] > distance[1] + graph[1][3])
distance[3] = 9999; distance[1] = 0; graph[1][3] = 24; distance[3] = distance[1] + graph[1][3] = 24.
pre[3] = 1;
if (graph[1][4] == 35 != 0)
if (distance[4] > distance[1] + graph[1][4])
distance[4] = 9999; distance[1] = 0; graph[1][4] = 35; distance[4] = distance[1] + graph[1][4] = 35.
if (graph[1][5] == 16 != 0)
if (distance[5] > distance[1] + graph[1][5])
distance[5] = 9999; distance[1] = 0; graph[1][5] = 16; distance[5] = distance[1] + graph[1][5] = 16.
pre[5] = 1;
if (graph[2][1] == 3 != 0)
if (distance[1] < distance[2] + graph[2][1])
distance[1] = 0; distance[2] = 3; graph[2][1] = 3; continue;
if (graph[2][3] == 5 != 0)
if (distance[3] > distance[2] + graph[2][3])
distance[3] = 24; distance[2] = 3; graph[2][3] = 5; distance[3] = distance[2] + graph[2][3] = 8.
pre[3] = 2;
if (graph[2][4] == 6 != 0)
if (distance[4] > distance[2] + graph[2][4])
distance[4] = 35; distance[2] = 3; graph[2][4] = 6; distance[4] = distance[2] + graph[2][4] = 9.
pre[4] = 2;
if (graph[2][5] == 17 != 0)
if (distance[5] < distance[2] + graph[2][5])
distance[5] = 16; distance[2] = 3; graph[2][5] = 17; continue;
path for node 3 is: while (pre[j] != 0)
arr[1] = pre[j] = pre[3] = 2; j = pre[3] = 2; arr[1] = pre[2] = 1; 1 → 2 → 3; distance = 8. Floyd Code #include <stdio.h> #include <stdlib.h> #include <string>
/* Floyd's All pairs shortest path algorithm (O (n^3) ).
input is adjacency matrix output is matrix of shortest paths. C is the adjacency matrix.
A is the all pairs shortest paths matrix.
we assume that A is allocated by the caller. */ int Floyd (int *A, int n) {
int i, j, k;
// for each route via k from i to j pick any better routes and // replace A[i][j] path with sum of paths i-k and j-k
for (k = 0; k < n; k++) for (i = 0; i < n; i++) for (j = 0; j < n; j++)
if ( A[i*n + k] + A[k*n + j] < A[i*n + j]) { // A[i][j] = A[i][k] + A[k][j];
A[i*n + j] = A[i*n + k]+ A[k*n + j]; }
return 0; }
void FloydTest() { int n = 5, i, j, k; k = 0; int *C = new int[n*n];
int x1[] = { 3, 24, 35, 16, 5, 6, 17, 7, 38, 19 }; for (i = 0; i < n; i++) for (j = i+1; j < n; j++) { C[j*n + i] = C[i*n + j] = x1[k]; k++; } for (i = 0; i < n; i++) C[i*n + i] = 0; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { printf ("%d ", C[i*n + j]); } printf ("\n"); }
int *A = new int[n*n]; for (i = 0; i < n; i++) for (j = 0; j < n; j++)
if ( C[i*n + j] == 0) {
A[i*n + j] = 9999; // Does this look like infinity? }
else {
A[i*n + j] = C[i*n + j]; }
// set the diagonals to zero for (i = 0; i < n; i++) {
A[i*n + i] = 0; } Floyd (A, n);
for (i = 0; i < n; i++) for (j = i+1; j < n; j++) {
} printf("\n"); delete []A; delete []C; }
int main() { FloydTest(); }
Code Maple Floyd 1 with(GraphTheory): G := Graph( { [{1, 2}, 3], [{1, 3}, 24], [{1, 4}, 35], [{1, 5}, 16], [{2, 3}, 5], [{2, 4}, 6], [{2, 5}, 17], [{3, 4}, 7], [{3, 5}, 38], [{4, 5}, 19] } ); DrawGraph(G); Floyd := proc(G::Graph) local i, j, k, n, A, B; A := WeightMatrix(G); n := NumberOfVertices(G); B := Matrix(n);
if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if; for i from 1 to n do for j from 1 to n do if A[i, j] > 0 then for k from 1 to n do if A[i, k] > 0 then
if A[j, k] < A[j, i] + A[i, k] then B[j, k] := A[j, i] + A[i, k]; end if; end if;
end do; end if;
end do; end do; return B;
end proc: A := Floyd(G);
Code Maple Floyd 2
with(GraphTheory): with(RandomGraphs): Floyd := proc(G::Graph)
local M, M1, M2, i, j, a, n, k;
M := WeightMatrix(G); n := NumberOfVertices(G);
k := 1; M1 := Matrix( M, datatype = anything); M2 := Matrix(n); for i from 1 to n do
if [i, j] ∉ Edges(G) and i != j then M1[i, j] := ∞ else M2[i, j] := j; end if;
end do; end do; while (k ≤ n) do
for i from 1 to n do for j from 1 to n do
a := M1[i, k] + M1[k, j]; if (a < 0) and (i = j) then
error "Co mach am"; end if; if (M1[i, j] > a) then
M1[i, j] := a; M2[i, j] := M2[i, k]; end if; end do; end do;
k := k + 1; end do; print( M1, M2 ); end proc: G1 := RandomDigraph( 5, 10, weights = -10..10 ); DrawGraph(G1); Floyd(G1); Chu trình Euler Euler Cycle
Fleury Algorithm for finding an Euler Cycle
- Starting from arbitrary vertex and using two following rules:
- Rule 1: Remove the edges were browsed and isolated vertices (điểm cô lập). - Rule 2: At every vertices, we only use one path.
> with(GraphTheory): with(SpecialGraphs): G := CompleteGraph(5); DrawGraph(G);
IsEulerian( G, 'T'); true;
T = Trail( 1, 2, 3, 1, 4, 2, 5, 3, 4, 5, 1);
- Starting from vertex 1; Trong số các đỉnh kề với đỉnh 1 thì đỉnh 2 là đỉnh nhỏ nhất và cạnh {1, 2} chưa qua, thêm cạnh {1, 2} vào T.
- Trong số các đỉnh kề với đỉnh 2 thì đỉnh 3 là đỉnh nhỏ nhất và cạnh {2, 3} chưa qua, thêm cạnh {2, 3} vào T.
- Trong số các đỉnh kề với đỉnh 3 thì đỉnh 1 là đỉnh nhỏ nhất và cạnh {3, 1} chưa qua, thêm cạnh {3, 1} vào T.
- Trong số các đỉnh kề với đỉnh 1 thì đỉnh 4 là đỉnh nhỏ nhất và cạnh {1, 4} chưa qua, thêm cạnh {1, 4} vào T.
- Trong số các đỉnh kề với đỉnh 4 thì đỉnh 2 là đỉnh nhỏ nhất và cạnh {4, 2} chưa qua, thêm cạnh {4, 2} vào T.
DeleteEdge(G, { {1, 2}, {2, 3}, {3, 1}, {1, 4}, {4, 2} } ); DrawGraph(G);
Euler Cycle Maple Code 1 with(GraphTheory):
with(RandomGraphs): Euler := proc(G::Graph, x0)
global n, Result, A, B, t1; local i, j, t, x, Kt; x:= x0; Kt := { };
Kt := { op( Neighbors(G, x) ) }; for i in Kt do
if B[x, i] != 0 then
Result[t1] := i; t1 := t1 + 1;
B[x, i] := 0; B[i, x] := 0; Euler(G, i); end if;
end do; end proc:
main := proc(G::Graph, x0)
global n, A, B, t1, Result; local i, t; n := NumberOfVertices(G); t := 0;
A := AdjacencyMatrix(G); Result := array(1..n.n); B := A; t1 := 2;
print( DrawGraph(G) ); if not IsConnected(G) then
return ("Do thi nay ko lien thong"); end if;
for i in Vertices(G) do
if (Degree(G, i) mod 2 = 1) then t := t + 1; end if;
end do;
if (t != 0 and (t != 2 or (Degree(G, x0) mod 2) = 0 ) ) then error ("Dont have any Euler");
end if; for i from 1 to n.n do Result[i] := 0; end do; Euler(G, x0); Result[1] := x0; print( Result ); end proc:
G1 := RandomGraph(5, 8, Connected); DrawGraph(G1); main(G1, 4);
Euler Cycle Maple Code 2
with(GraphTheory): with(RandomGraphs): with(LinearAlgebra): Euler := proc(G::Graph, x0)
local M, n, t, i, Road, Stack, x, X, k;
# M: Ma trận kề, n: số đỉnh của đồ thị G, Road: biểu diễn đường đi Euler. # Stack: ngăn xếp, x: phần tử cuối của Road, X: tập hợp.
# k: số phần tử của Stack.
if (IsConnected(G) = false or IsDirected(G) = true) then error ("Data Error"); end if;
M := AdjacencyMatrix(G); t := 0; n := nops( Vertices(G) ); print(n); for i in Vertices(G) do
if (Degree(G, i) mod 2 = 1) then t := t + 1; end if;
end do;
if (t != 0 and (t != 2 or (Degree(G, x0) mod 2) = 0 ) ) then error ("Dont have any Euler");
Stack := Matrix([x0]); X := { }; Road := Matrix([ ]);
while Equal( Stack, Matrix([ ]) ) = false do k := ArrayNumElems(Stack);
x := Stack( 1, k ); i := 1;
while (i < n + 1) and (M(x, i) = 0 or (M(x, i) = 1 and i ∈ X) ) do i := i + 1;
if (i = n + 1) then break; end if; end do;
if (i < n + 1) then Stack := <Stack|i>; M[i, x] := 0;
else if Equal( M, AdjacencyMatrix(G) ) then M[ Stack( k ), Stack( k - 1 ) ] := 1;
end if;
Road := <Stack( 1, k ) | Road>; X := X union { Stack( k ) };
Stack := DeleteColumn( Stack, [k] ); end if;
end do; print(Road); end proc:
G1 := RandomGraph(5, 8, Connected); DrawGraph(G1); Euler(G1, 4);
Stack:
with(LinearAlgebra): Stack := Matrix([3]);
Stack := <Stack | 5>; # Thêm phần tử 5 vào Stack; Stack := <Stack | 7>;
k := ArrayNumElems(Stack): # k là số phần tử của Stack; i := Stack(1, k): # i là phần tử cuối của Stack;
j := Stack(1, 1): # i là phần tử đầu của Stack; print(`k = `, k, `i = `, i, `j = `, j);
Stack := DeleteColumn( Stack, [k] ); # Delete phần tử cuối của Stack;
s := stack[new](1, 2, 3): # Khởi tạo Stack.
stack[push]( 7, s ): # Thêm phần tử 7 vào Stack; print(s);
i := stack[pop](s); # i là phần tử cuối của Stack; with(GraphTheory): with(RandomGraphs): G := CompleteGraph(7); DrawGraph(G); IsEulerian(G, ‘T’); T Trail( 1, 2, 3,/ 1, 4, 2, 5,/ 1, 6, 2, 7,/ 3, 4, 5, 3,/ 6, 4, 7, 5,/ 6, 7, 1) 1 2 3 4 5 6 7 1 0 1 1 1 1 1 1 2 0 1 1 1 1 1 3 0 1 1 1 1 4 0 1 1 1 5 0 1 1 6 0 1 7 0 int x[] = { 1, 1, 1, 1, 1, 1, / 1, 1, 1, 1, 1, / 1, 1, 1, 1, / 1, 1, 1, 1, 1, 1 }; int x[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
Euler Cycle C++ Code #include <stdio.h> #include <stack.h> int Matrix[100][100]; int n; void Create() { int i, j, k1; n = 7; k1 = 0; int x[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; for (i = 0; i < n; i++) for (j = i+1; j < n; j++) {
Matrix[j][i] = Matrix[i][j] = x[k1]; k1++; } for (i = 0; i < n; i++) Matrix[i][i] = 0; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) printf ("%5d", Matrix[i][j]); printf("\n"); } printf("\n"); }
/* chu trinh Euler bang phuong phap stack
1. Tim duong di tai 1 diem: Kiem tra xem so bac le co = 2 khong 2. Tim duong di tai tat cac cac diem : dung phuong phap de quy */ int KiemTra() { int i, j, d, s; d = 0; for(i = 0; i < n; i++) { s = 0; for (j = 0; j < n; j++) s += Matrix[i][j];
if (s % 2 != 0) d++; // Kiem tra xem la so dinh bac co chan hay khong neu khong thi d++ } if (d > 0) return (false); return (true); } void Euler() {
int dCE = -1; // vi xet khoang tu 0 -> n-1; stack <int> myStack;
int CE[100]; // Cycle Euler dung de luu nhung phan tu lay tu ngan xep. int v, x, u; u = 0; // Chon u = 0 de ta lay diem bat dau la so 1.
myStack.push(u); do {
v = myStack.top(); // chon x lam phan tu dau. x = 0;
while (x < n && Matrix[v][x] == 0) x++; if (x >= n) { dCE++; CE[dCE] = v; myStack.pop(); } else { myStack.push(x);
Matrix[v][x] = 0; Matrix[x][v] = 0; // xoa cac canh di }
printf ("Co chu trinh Euler \n"); for (int i = dCE; i>= 0; i--)
printf ("%5d", CE[i]+1); } int main() { Create(); if(KiemTra()) Euler(); else
printf ("Khong co chu trinh Euler \n"); } with(GraphTheory): with(RandomGraphs): G := CompleteGraph(5); DrawGraph(G); IsEulerian(G, ‘T’); T Trail(1, 2, 3, 1, 4, 2, 5, 3, 4, 5, 1); 1 2 3 4 5 1 0 1 1 1 1 2 0 1 1 1 3 0 1 1 4 0 1 5 0 int x[] = { 1, 1, 1, 1, / 1, 1, 1, / 1, 1, 1}; int x[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; Chu trình Hamilton Quy tắc xác định đồ thị Hamilton
- Rule 1: Tất cả các cạnh kề với 1 đỉnh bậc 2 phải ở trong H.
- Rule 2: Ko có chu trình con nào (chu trình có chiều dài nhỏ hơn n) được tạo thành trong quá trình xây dựng H.
- Rule 3: Khi chu trình Hamiltom mà ta đang xây dựng đi qua đỉnh i thì xóa tất cả cạnh kề với i mà chưa đi qua. Điều này có thể cho ta 1 số đỉnh bậc 2 và ta lại có thể dùng quy tắc 1.
- Rule 4: Ko có đỉnh cô lập hay cạnh treo nào được tạo nên sau khi dùng quy tắc 3.
Hamilton Maple Code with(GraphTheory): with(SpecialGraphs): with(RandomGraphs): Hamilton := proc(G::Graph)
global n, M, Road, check, Kt; local i, k, E; n := NumberOfVertices(G); E := Graph(n); DrawGraph(G); check := false;
M := AdjacencyMatrix(G); Road := array(1..n); k := 1; for i from 1 to n do
if check = true then break;
else
Kt := {i}; Road[1] := i; Browse(i, 1); end if;
end do;
if check = false then
error "Ko ton tai duong di Hamilton"; else
for i from 1 to n-1 do
AddEdge( E, { Road[i], Road[i+1] } ); end do;
HighlightEdges(G, E, red);
print( DrawGraph(G) ); print(Road); end if;
end proc:
Browse := proc(x0, k)
global M, Road, Kt, check; local i; if k = n then
check := true; end if; if check = false then
for i from 1 to n do
Kt := Kt union {i};
if check = false then Road[k+1] := i; end if; Browse(i, k+1); Kt := Kt \ {i}; end if; end do; end if; end proc: G1 := PetersenGraph(); AddEdge(G1, {1, 3}); Hamilton(G1); > with(GraphTheory): with(SpecialGraphs): G := PetersenGraph(); AddEdge(G, {1, 3}); DrawGraph(G); IsHamiltonian(G, 'T'); T = { 1, 2, 9, 8, 5, 4, 10, 6, 7, 3, 1 } Đỉn 1 2 3 4 5 6 7 8 9 10
h 1 0 1 1 0 1 1 0 0 0 0 2 0 1 0 0 0 0 0 1 0 3 0 1 0 0 1 0 0 0 4 0 1 0 0 0 0 1 5 0 0 0 1 0 0 6 0 1 0 0 1 7 0 1 0 0 8 0 1 0 9 0 1 0 0 int x[] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, / 1, 0, 0, 0, 0, 0, 1, 0, / 1, 0, 0, 1, 0, 0, 0, / 1, 0, 0, 0, 0, 1, / 0, 0, 1, 0, 0, / 1, 0, 0, 1, / 1, 0, 0, 1, 0, 1 }; int x[] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1 }; Code Hamilton C++ #include <stdio.h> #define max 20 int a[max][max];
int Mark[max], c[max]; int n; void Create() { int i, j, k1; n = 10; k1 = 0; int x[] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1 }; for (i = 0; i < n; i++) for (j = i+1; j < n; j++) { a[j][i] = a[i][j] = x[k1]; k1++; } for (i = 0; i < n; i++) a[i][i] = 0;
for (i = 0; i < n; i++) Mark[i] = 0;
c[0] = 0; Mark[0] = 1; // Xuat phat tu dinh 0. } void ShowPath() { for (int k = 0; k < n; k++) printf ("%4d", c[k]+1); // In ra số hiệu đỉnh + 1 printf ("%4d \n", c[0]+1); } void Hamilton(int k) { for (int i = 0; i < n; i++)
if (Mark[i] == 0 && a [ c[k-1] ] [i] != 0) { Mark[i] = 1; c[k] = i;
if (k == n-1) { if (a [ c[k]] [c[0] ] != 0) ShowPath(); } else Hamilton(k+1); Mark[i] = 0; } } int main() { Create(); Hamilton(1); } void Hamilton(int k) { for (int i = 0; i < n; i++)
if (Mark[i] == 0 && a [ c[k-1] ] [i]) { // Nếu đỉnh k chưa duyệt đến và có nối với đỉnh vừa được ghi nhận trước đó (thứ j-1, số hiệu là c[j-1])
Mark[i] = 1; c[k] = i; // Xem như duyệt đỉnh k và nó là đỉnh thứ j theo trình tự ghi nhận.
if (k == n-1) { // Nếu đã ghi nhận đủ số đỉnh
if (a [c[k]] [c[0]] != 0) ShowPath(); // Nếu đỉnh cuối có nối với đỉnh đầu tiên thì hiển thị chu trình.
}
else Hamilton(k+1); // Nếu chưa ghi nhận đủ n đỉnh thì đệ quy để tìm đỉnh thứ j+1.
Mark[i] = 0; // Quay lui chính là chỗ này đây. }
}
IsHamiltonian(G, 'T');
- Bắt đầu từ đỉnh 1, lấy cạnh {1, 2}, {1, 3}, xóa cạnh {1, 6}, {1, 5} (do đã lấy 2 cạnh kề với đỉnh 1). Lấy {2, 3} sẽ tạo thành chu trình {1, 2, 3}, xóa cạnh {2, 3}. G := DeleteEdge(G, { {1, 6}, {1, 5}, {2, 3} } );
DrawGraph(G);
- Các đỉnh 5, 6 trở thành đỉnh bậc 2, lấy cạnh {5, 4}, {5, 8}, {6, 7}, {6, 10}.
- Lấy cạnh {2, 9} để có liên thông. Ta có chu trình { 9, 10, 6, 7, 8, 9 }; Trong đó ta đã lấy cạnh {6, 7}, {6, 10} vậy bỏ cạnh {7, 8}.
G := DeleteEdge(G, {7, 8} ); DrawGraph(G);
- Giờ ta có đỉnh 7 và đỉnh 8 là đỉnh bậc 2. Lấy cạnh {7, 6}, {7, 3}, {8, 5}, {8, 9}. - Ta có chu trình {1, 3, 4, 5, 8, 9, 2, 1} bậc 7 nhỏ hơn 10, vậy xóa cạnh {3, 4} vì các cạnh khác đã add.
- Ta cũng có chu trình { 9, 10, 6, 7, 3, 1, 2, 9} bậc 7 nhỏ hơn 10, vậy xóa cạnh {9, 10} vì các cạnh khác đã add.
DrawGraph(G); Chu trình 2: > with(GraphTheory): with(SpecialGraphs): G := PetersenGraph(); AddEdge(G, {1, 3}); DrawGraph(G); IsHamiltonian(G, 'T'); T = { 1, 2, 9, 8, 5, 4, 10, 6, 7, 3, 1 }
- Bắt đầu từ đỉnh 1, lấy cạnh {1, 2}, {1, 3}, xóa cạnh {1, 6}, {1, 5} (do đã lấy 2 cạnh kề với đỉnh 1). Lấy {2, 3} sẽ tạo thành chu trình {1, 2, 3}, xóa cạnh {2, 3}. G := DeleteEdge(G, { {1, 6}, {1, 5}, {2, 3} } );