Code cho các bài tập Lí thuyết đồ thị về Danh sách cung, Ma trận đỉnhcung đỉnhđỉnh duyệt chiều rộng thì lấy cái bên phải cùng sang xét 8 duyệt chiều sâu thì xét cái đầu tiên bên trái sang bằng ngôn ngữ C các hàm add edge adjacent
Trang 11 Code LTDT Tuần 5
2 Danh sách cung
3 Ma trận kề
4 Ma trận đỉnh-cung (dạng chuyển đồi)
5 Ma trận đỉnh-đỉnh (dạng chuyển đồi)
6 Đọc đồ thị từ tập tin
7 tuần 4 duyệt chiều rộng thì lấy cái bên phải cùng sang xét
8 duyệt chiều sâu thì xét cái đầu tiên bên trái sang
9
-
-10
-
-11
-
-12
-
-13 #############################################THEO DANH SACH CUNG################################################################################## 14 !!!Cấu trúc khai báo của 1 Ctr Danh sach Cung: 15 $$Code: 16 #include <stdio.h> 17 #define MAX_M 500 18 //Cấu trúc Edge lưu dữ liệu của 1 cung 19 typedef struct { 20 int u, v; 21 } Edge; 22 //Khai báo cấu trúc dữ liệu Graph 23 typedef struct { 24 int n, m; 25 Edge edges[MAX_M]; 26 } Graph; 27 28 29 30 !!!!!Đọc dữ liệu trong tập tin dt.txt(Hàm này nằm trong hàm MAIN) 31 //Đọc số đỉnh và số cung & khởi tạo đồ thị 32 FILE* file = fopen("dt.txt", "r"); 33 //freopen("dt.txt", "r", stdin); 34 35 !!!!==> sau đó đổi scanf thành fscanf(file,"? %d",&) 36 !!!!==> xong r fclose(file); de dong file xong moi tới hàm để in ra màn hình 37
-
-38
-
-39
-
-40
-
-41
-
-42 1 Hàm init_graph có số đỉnh bằng n và số cung bằng 0 ( PP Danh sách cung): 43 $$CODE: 44 void init_graph(Graph *pG, int n){ 45 pG->n=n; 46 pG->m=0; 47 } 48
-
-49 2 Hàm add_edge() (Hàm chung nhớ tùy vào đề bớt các điều kiện): 50
-51 Cơ bản chỉ cần điều kiện(trùng được , uv và vu phân biệt): 52 $$CODE: 53 54 void add_edge(Graph *pG, int u, int v) {
55 if (u>0 && u<=pG->n && v>0 && v<=pG->n) {
56 // Thêm cung (u, v) vào danh sách cung của đồ thị
57 pG->edges[pG->m].u = u;
58 pG->edges[pG->m].v = v;
Trang 259 pG->m++;
60 }
61 } 62
-63 Nâng cao nếu uv có rồi không thêm vào nữa và các tham số đều hợp lệ (nếu không hợp lệ thêm điều kiện vào if của hàm void) Có hướng: 64 $$CODE: 65 66 void add_edge(Graph *pG, int u, int v) { 67 for (int i = 0; i < pG->m; i++) 68 if (pG->edges[i].u == u && pG->edges[i].v == v) 69 return; 70 pG->edges[pG->m].u = u; 71 pG->edges[pG->m].v = v; 72 73 pG->m++; 74 } 75
-76 Nâng cao nếu cung (u, v) hoặc cung (v, u) đã có trong đồ thị rồi thì bỏ qua, không thêm vào nữa(không cho (1,1) luôn) Vô hướng: 77 void add_edge(Graph *pG, int u, int v) { 78 if (u == v) 79 return; 80 for (int i = 0; i < pG->m; i++) 81 if ((pG->edges[i].u == u && pG->edges[i].v == v) || 82 (pG->edges[i].u == v && pG->edges[i].v == u) || u==v) 83 return; 84 pG->edges[pG->m].u = u; 85 pG->edges[pG->m].v = v; 86 pG->m++; 87 } 88
-
-89
-
-90
-
-91 92 3.Hàm adjacent(Graph *pG, int u, int v) để kiểm tra đỉnh u có kề với đỉnh v không theo mẫu (prototype): 93 $$CODE: 94 95 int adjacent(Graph *pG, int u, int v) { 96 int i; 97 for (i = 0; i < pG->m; i++) 98 if ((pG->edges[i].u == u && pG->edges[i].v == v) || 99 (pG->edges[i].u == v && pG->edges[i].v == u)) 100 return 1; 101 return 0; 102 } 103 104
-
-105
-
-106
-
-107
108 4 Hàm degree(Graph *pG,int u) Đếm bậc của đỉnh u của đồ thị bất kỳ:
109 $$CODE:
110 int degree(Graph *pG, int u) {
111 int e, deg_u = 0;
112 //Duyệt qua từng cung 0, 1, 2, …, m - 1
113 for (e = 0; e < pG->m; e++) {
114 //Nếu cung có dạng (u, -)
115 if (pG->edges[e].u == u)
117 //Nếu cung có dạng (-, u)
118 if (pG->edges[e].v == u)
Trang 3119 deg_u++;
120 }
121 122 return deg_u; 123 } 124 Trong ham main: 125 for (int u = 1; u <= n; u++){ 126 printf("deg(%d) = %d\n", u, degree(&pG, u)); 127 }
128 return 0; // nam ngoai ham for 129 130 131
-
-132
-
-133
-
-134 !!!!!!!!5 //Đọc m cung và thêm vào đồ thị( Bo Tro trong ham Main) 135 !!!!!!!!!rong Hàm Main: 136 int e; 137 for (e = 0; e < m; e++) { 138 scanf("%d%d", &u, &v); ||nếu có đọc file nhớ đồi thành fscanf(file,"",&);|| 139 add_edge(&G, u, v); 140 }
141 142
-
-143
-
-144
-
-145 -####################################################THEO DANH SACH
CUNG############################################################ -146
-
-147
-
-148
-
-149 150 151 152 -##đồ thị vô hướng và in các đỉnh kề của các đỉnh ra màn hình.Biểu diễn đồ thị bằng phương pháp "Danh sách
cung".(neighbours(2))#### -
-153 ## 154 Ham in cac dinh ke cua dinh ra man hinh !!trong main!!! (cho đồ thị vô hướng!!!!!!!!) 155 ###neighbours##### 156 for (int u = 1; u <= n; u++) { 157 printf("neighbours(%d) = ", u); 158 for (int v = 1; v <= n; v++) 159 if (adjacent(&pG, u, v)) 160 printf("%d ", v); 161 printf("\n"); 162 }
163 164 165 return 0; 166 167
-
-168 !! cho đồ thị !!!có hướng!!! thì cái hàm adjacent bỏ cái điều kiện u=v && v=u sau || là
done hàm neighbours vẫn giử nguyên
169 int adjacent(Graph *pG,int u, int v){
170 int i;
171 for(i=0;i<pG->m;i++){
Trang 4172 if((pG->edges[i].u==u && pG->edges[i].v==v)){
173 return 1;
174 }
175 }return 0; 176 } 177 178 -MA TRAN
KEEEEEEEEEEEEEE -179 180 khai bao MA TRAN KE 181 #include <stdio.h> 182 #define MAX_N 100 183 184 typedef struct { 185 int n, m; 186 int A[MAX_N][MAX_N]; 187 } Graph; 188 #####Hàm init_graph của ma trận kề ( đơn đồ thị vô hướng hoặc đồ thị vô hướng có thể chứa đa cung đa khuyên) 189 void init_graph(Graph *pG, int n){ 190 pG->n=n; 191 pG->m=0; 192 for(int u=1;u<=n;u++){ 193 for(int v=1;v<=n;v++){ 194 pG->A[u][v] = 0; 195 196 }
197 }
198 }
199 200 #### Hàm add_edge của ma trận kề ( đơn đồ thị vô hướng hoặc đồ thị vô hướng có thể chứa đa cung đa khuyên) cứ vô hướng là sử dụng 201 202 void add_edge(Graph *pG,int u,int v){ 203 pG->A[u][v] += 1; 204 if(u != v){ 205 pG->A[v][u] += 1; 206 }
207 pG->m++; 208 }
209
-
-210
-
-211 #######MA TRẬN KỀ đồ thị có hướng đa cung đa khuyên 212 #######chỉ cần thay đổi hàm add_edge không cần if cứ có hướng là sdung hàm này 213 void add_edge(Graph *pG, int u, int v) { 214 pG->A[u][v] += 1; 215 pG->m++; 216 }
217 218
-
-219 ##Hàm In ma trận kề ra man hình 220 printf("Ma tran ke:\n"); 221 for (int u = 1; u <= n; u++) { 222 for (int v = 1; v <= n; v++) 223 printf("%d ", pG.A[u][v]); 224 printf("\n"); 225 }
226 227 return 0; 228 229 -Các hàm tính bậc của đỉnh trong Ma trận kề các loại đồ
thị -
-230
231 * #####hàm Degree "Ma trận kề" dùng để lưu trữ các đồ thị vô hướng (có thể chứa đa
cung và chứa khuyên)
Trang 5232 int degree(Graph *pG,int u){
233 int v, deg_u=0;
234 for(v=1; v<= pG->n ; v++){
235 deg_u += pG->A[u][v];
236 }
237 return deg_u += pG->A[u][u]; 238 }
239 240
-241 242 * #####hàm Degree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa cung và chứa khuyên) 243 int degree(Graph *pG,int u){ 244 int v, deg_u=0; 245 for(v=1; v<= pG->n ; v++){ 246 deg_u += pG->A[u][v] + pG->A[v][u]; 247 }
248 return deg_u; 249 }
250
-251 252 253 * #####Hàm indegree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa cung và chứa khuyên) 254 int indegree(Graph *pG, int u){ 255 int v, deg_u=0; 256 for(v = 1;v<= pG->n; v++){ 257 deg_u += pG->A[v][u]; 258 }
259 return deg_u; 260 }
261
-262 263 * ####Hàm outdegree "Ma trận kề" dùng để lưu trữ các đồ thị có hướng (có thể chứa đa cung và chứa khuyên) Giống hàm degree vô hướng but return deg_u 264 int outdegree(Graph *pG,int u){ 265 int v, deg_u=0; 266 for(v=1; v<= pG->n ; v++){ 267 deg_u += pG->A[u][v]; 268 }
269 return deg_u; 270 }
271 272 * ##### Hàm neighbours in ra trong ma trận kề vô hướng giống dsach cung thay đổi ngay if còn có hướng thì đổi điều kiện trong add_edge 273 for (int u = 1; u <= n; u++) { 274 printf("neighbours(%d) = ", u); 275 for (int v = 1; v <= n; v++) 276 if (pG.A[u][v]) 277 printf("%d ", v); 278 printf("\n"); 279 }
280 281 282 return 0; 283
-
-284
-
-285
-
-286
287 #### Dạng chuyển đổi
288
289 **** Từ Ma trận kề in ra các các cung kề dạng bài này không cần hàm init với hàm add_edge
290
Trang 6291 **Hàm khai báo:
292 #include <stdio.h>
293 #define MAX_N 100
294
295 typedef struct {
297 int A[MAX_N][MAX_N];
298 } Graph;
299
300 int main() {
301 Graph pG;
302 int n, a;
303
304 //Đọc số đỉnh và gán cho G.n
305 scanf("%d", &n);
306 pG.n = n;
307 **sau đó
308 //Đọc ma trận kề và gán giá trị vào G.A
309 for (int u = 1; u <= n; u++) {
310 for (int v = 1; v <= n; v++) {
311 scanf("%d", &a);
312 pG.A[u][v] = a;
313 }
314 }
315 **### Hàm in ra nè có điều kiện khi u v (U<=v) (Đồ thị có hướng) 316 **//Liệt kê các cung của G theo thứ tự u <= v sài chung cho các dạng chuyển dồi từ ma trận in ra mỗi cung trên 1 dòng theo mẫu: u v (u≤v) 317 318 for (int u = 1; u <= n; u++) { 319 for (int v = u; v <= n; v++) { tùy chỉnh dòng này 320 for (int k = 0; k < pG.A[u][v]; k++) 321 printf("%d %d\n", u, v); 322 }
323 }
324 return 0; 325 **### Hàm in ra nè 0 có điều kiện khi u v chỉ cần sửa dòng for thứ 2 thành v = 1 là ok vẫn là ma trận kề in ra các cung (Đồ thị vô hướng) 326 327 328
-
-329 ### hàm in ra danh sách kề (In ra n dòng, mỗi dòng tương ứng với một danh sách kề.) của ĐỒ THỊ VÔ HƯỚNG giống hàm in của đồ thị vô hướng for 2 v=1 chỉ sửa dòng for thứ 3 in ra "v" và dòng for bự in "0\n" nhớ return 0; ngoài hàm 330 (In ra n dòng, mỗi dòng tương ứng với danh sách kề của 1 đỉnh.) 331 //G.A[u][v] cho biết số cung đi từ u đến v 332 for (int u = 1; u <= n; u++) { 333 for (int v = 1; v <= n; v++) { 334 for (int k = 0; k < pG.A[u][v]; k++){ 335 printf("%d ", v); 336 }
337 }
338 printf("0\n"); 339 }
340 return 0; 341 ### hàm In ra n dòng, mỗi dòng tương ứng với danh sách kề của 1 đỉnh giống hàm trên 342 343
-
-344
-
-345 Viết chương trình bằng ngôn ngữ C cho phép người nhập vào danh sách kề của các đỉnh
trong một đồ thị vô hướng và in ma trận kề của nó màn hình
346 Dạng nhập dsach kề in ra ma trận( không khai báo a trong hàm main)
347
348 ####Hàm Chung:
349 #include <stdio.h>
350 #define MAX_N 100
Trang 7351
352 * typedef struct {
354 int A[MAX_N][MAX_N];
355 }Graph;
356
357 * void init_graph(Graph *pG, int n) {
358 pG->n = n;
359
360 for (int u = 1; u <= n; u++)
361 for (int v = 1; v <= n; v++)
362 pG->A[u][v] = 0;
363 }
364
-365 * void add_edge(Graph *pG, int u, int v) { 366 pG->A[u][v] += 1; 367 }
368
-369 * int main() { 370 Graph pG; 371 int n; 372 scanf("%d", &n); 373 pG.n = n; 374 **//Đọc các danh sách kề 375 for (int u = 1; u <= n; u++) { 376 int v; 377 while (1) { 378 scanf("%d", &v); 379 if (v == 0) 380 break; 381 add_edge(&pG, u, v); 382 } của hàm while 383 } ngoặc này của hàm for 384 #*# hàm in ra ma trận kề sử dụng cho đồ thị vô hướng và có hướng luôn sài chung 385 for(int u=1;u<=n;u++){ 386 for(int v=1;v<=n;v++){ 387 printf("%d ",pG.A[u][v]); 388 }
389 printf("\n"); 390 }
391 return 0; 392 393
-
-394
-
-395 Ma Trận Đỉnh-Cung 396 ### Viết hàm add_edge(Graph* pG, int e, int x, int y) để thêm cung e = (x, y) vào đồ thị pG theo mẫu (prototype) Vô Hướng Không chứa khuyên 397 398 void add_edge(Graph* pG, int e, int x, int y) { 399 if (x >= 0 && x < pG->n && y >= 0 && y < pG->n) { 400 if (pG->A[x][e] == 0 && pG->A[y][e] == 0) { 401 pG->A[x][e] = 1; 402 pG->A[y][e] = 1; 403 }
404 }
405 }
406
407
408 ### Viết hàm List neighbors(Graph* pG, int u) trả về danh sách các đỉnh kề của u theo
mẫu (prototype): Vô Hướng Không chứa khuyên
409
410 List neighbors(Graph* pG, int x) {
412 make_null(&L);
413 int e, y;
414 for (y = 1; y <= pG->n; y++) {
415 if (x == y) continue;
Trang 8416 for (e = 1; e <= G->m; e++)
417 if (pG->A[x][e] > 0 && pG->A[y][e] > 0) {
422 return L;
423 }
424
-425 "Ma trận đỉnh - đỉnh" dùng để biểu diễn các đơn đồ
thị vô hướng
426
427 Viết hàm int deg(Graph* G, int x) để tính bậc của đỉnh u theo mẫu (prototype): ( *G chứ
không phải *pG)
428
429 int deg(Graph* pG, int x){
430 int de=0;
432 for(i=1;i<=pG->n;i++)
433 if(pG->A[x][i]==1)
435 return de;
436 }
437
438
440 Viết chương trình tính và in ra màn hình đỉnh có bậc lớn nhất và bậc tương ứng của
nó
441 Nếu có nhiều đỉnh có bật bằng nhau thì in ra đỉnh có số thứ tự nhỏ nhất
442
-443 ** #include <stdio.h>
444 #define MAX_N 100
445
446 * typedef struct {
447 int A[MAX_N][MAX_N];
449 } Graph;
450
451 * void init_graph(Graph *pG, int n) {
452 pG->n = n;
453 for (int i = 0; i < n; ++i) {
454 for (int j = 0; j < n; ++j) {
455 pG->A[i][j] = 0;
458 }
459
460 * void add_edge(Graph *pG, int u, int v) {
461 pG->A[u][v] = 1;
462 pG->A[v][u] = 1;
463 }
464
465 * int deg(Graph *pG, int u) {
466 int degree = 0;
467 for (int i = 0; i < pG->n; ++i) {
468 degree += pG->A[u][i];
470 return degree;
471 }
472
473 * int main() {
474 Graph pG;
475 int n, m;
476 scanf("%d %d", &n, &m);
477 init_graph(&pG, n);
478 * for (int i = 0; i < m; ++i) {
480 scanf("%d %d", &u, &v);
481 add_edge(&pG, u - 1, v - 1);
Trang 9482 }
483 int maxDegree = -1;
484 int maxVertex = -1;
485 * for (int u = 0; u < n; ++u) {
486 int degree = deg(&pG, u);
487 if (degree > maxDegree || (degree == maxDegree && u < maxVertex)) {
492 *In printf("%d %d\n", maxVertex + 1, maxDegree);
493
494 return 0;
495 }
496
497
499 Hãy viết chương trình đọc đồ thị từ tập tin và hiển thị ma trận kề của đồ thị này
500
501 Giả sử đồ thị được cho là đồ thị vô hướng đơn
502
503 Đầu vào (Input):
504
505 Dữ liệu đầu vào được nhập từ tập tin dt1.txt với định dạng:
506
507 - Dòng đầu tiên chứa 2 số nguyên n và m, tương ứng là số đỉnh và số cung
508
509 - m dòng tiếp theo mỗi dòng chứa 2 số nguyên u v mô tả cung (u, v)
510
511 Đầu ra (Output):
512
513 In ra Ma trận kề (0/1) của đồ thị
514
515 #include <stdio.h>
516 #define MAX_N 100
517
518 * typedef struct {
519 int A[MAX_N][MAX_N];
521 } Graph;
522
523 * void init_graph(Graph *pG, int n) {
524 pG->n = n;
525 for (int i = 0; i < n; ++i) {
526 for (int j = 0; j < n; ++j) {
527 pG->A[i][j] = 0;
530 }
531
532 * void add_edge(Graph *pG, int u, int v) {
533 pG->A[u][v] = 1;
534 pG->A[v][u] = 1;
535 }
536
537 * void hienthi_matran(Graph *pG) {
538 for (int i = 0; i < pG->n; ++i) {
539 for (int j = 0; j < pG->n; ++j) {
540 printf("%d ", pG->A[i][j]);
542 printf("\n");
544 }
545
546 * int main() {
547 Graph pG;
548 int n, m;
549 * // Đọc file
550 FILE *file = fopen("dt1.txt", "r");
Trang 10551 if (file == NULL) {
552 printf("Cannot open file dt1.txt\n");
555 fscanf(file, "%d %d", &n, &m);
556 init_graph(&pG, n);
557 for (int i = 0; i < m; ++i) {
559 fscanf(file, "%d %d", &u, &v);
560 add_edge(&pG, u - 1, v - 1);
562 * // Đóng file
563 fclose(file);
564 * // hien thi ma tran
565 hienthi_matran(&pG);
566 return 0;
567 }
568
569
-
-570
571
572