Professional Documents
Culture Documents
TÊN ĐỀ TÀI
Đà Nẵng, 07/2022
MỤC LỤC
MỤC LỤC i
DANH MỤC HÌNH VẼ ii
MỞ ĐẦU i
1. TỔNG QUAN ĐỀ TÀI 1
2. CƠ SỞ LÝ THUYẾT 1
2.1. Ý tưởng 1
2.2. Cơ sở lý thuyết 1
3. TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN 1
3.1. Phát biểu bài toán 1
3.2. Cấu trúc dữ liệu 1
3.3. Thuật toán 1
4. CHƯƠNG TRÌNH VÀ KẾT QUẢ 1
4.1. Tổ chức chương trình 1
4.2. Ngôn ngữ cài đặt 1
4.3. Kết quả 1
4.3.1. Giao diện chính của chương trình 1
4.3.2. Kết quả thực thi của chương trình 1
4.3.3. Nhận xét đánh giá 1
5. KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 1
5.1. Kết luận 1
5.2. Hướng phát triển 1
TÀI LIỆU THAM KHẢO 2
1
DANH MỤC HÌNH VẼ
2
Đồ án lập trình tính toán
MỞ ĐẦU
Trong phần này, cần trình bày về: Mục đích thực hiện đề tài, mục tiêu đề tài,
phạm vi và đối tượng nghiên cứu, phương pháp nghiên cứu, cấu trúc của đồ môn học}
Mục đích thực hiện đề tài: Thông qua quá trình thực hiện đề tài có thêm kiến thức,
cũng
như áp dụng được những kiến thức đã học để giải quyết vấn đề, bài toán một cách
trơn
tru tối ưu nhất có thể.
Mục tiêu đề tài: giải quyết được bài toán được đưa ra.
Phạm vi và đối tượng nghiên cứu: sử dụng bao quát những kiến thức đã học và tập
trung
chủ yếu tại các cấu trúc trong cấu trúc dữ liệu, đối tượng nghiên cứu chính là cấu
trúc
dữ liệu tập hợp rời rạc và ứng dụng của nó.
Phương pháp nghiên cứu: sử dụng các tài liệu được phổ cập trên trường cũng như tìm
kiếm tài liệu từ Internet, đọc hiểu về cấu trúc dữ liệu tập hợp rời rạc, suy ra ý
tưởng áp
dụng kiến thức và hoàn thành đề bài.
Cấu trúc của đồ môn học:sau khi tìm hiểu các lý thuyết về về thuật toán Disjoint-
set và
các lý thuyết liên qua lên ý tưởng và giải quyết vấn đề được đưa ra, kiểm tra và
nâng
cấp thuật toán.
1
Đồ án lập trình tính toán
2. CƠ SỞ LÝ THUYẾT
2.1. Ý tưởng
Phân chia các sinh viên thành các nhóm khác nhau theo các nhóm mà sinh viên
thuộc về. Phương pháp này được gọi là cấu trúc dữ liệu tập hợp phân biệt duy trì
tập
hợp các tập hợp rời rạc và mỗi tập hợp được đại diện bởi đại diện của nó là một
trong
các thành viên của nó.
2.2. Cơ sở lý thuyết
2.2.1. Disjoint-set data structure
Cấu trúc dữ liệu tập hợp rời rạc , còn được gọi là cấu trúc dữ liệu liên
hợp-
tìm hoặc hợp nhất tìm tập hợp , là một cấu trúc dữ liệu lưu trữ một tập hợp các tập
hợp
rời rạc (không chồng chéo). Tương tự, nó lưu trữ một phân vùng của một tập hợp
thành
các tập con rời rạc. Nó cung cấp các hoạt động để thêm các tập hợp mới, hợp nhất
các
tập hợp (thay thế chúng bằng liên hiệp của chúng ) và tìm thành viên đại diện của
một
tập hợp.
2.2.2. Union (set theory)
Trong lý thuyết tập hợp, hợp (ký hiệu là ∪) của một tập hợp các tập hợp là
tập
hợp của tất cả các phần tử trong tập hợp. [1] Nó là một trong những phép toán cơ
bản
mà qua đó các tập hợp có thể được kết hợp và liên quan với nhau. Liên hợp nullary
đề
cập đến liên hợp của các tập hợp 0 và theo định nghĩa, nó tương đương với tập hợp
rỗng.
2.2.3. Forest
Rừng là một đồ thị vô hướng trong đó hai đỉnh bất kỳ được nối với nhau bằng
nhiều nhất một đường đi. Tương tự, rừng là một đồ thị xoay chiều vô hướng, tất cả
các
1
Đồ án lập trình tính toán
thành phần được kết nối của chúng là cây; nói cách khác, biểu đồ bao gồm sự kết hợp
rời rạc của các cây. Trong những trường hợp đặc biệt, biểu đồ bậc không (một khu
rừng
không có cây nào), một cây đơn lẻ và một biểu đồ không viền, là những ví dụ về
rừng.
Vì với mọi cây V - E = 1, chúng ta có thể dễ dàng đếm số cây trong một khu rừng
bằng
cách trừ đi hiệu số giữa tổng số đỉnh và tổng số cạnh. TV - TE = số cây trong rừng.
2
Đồ án lập trình tính toán
3.3. Thuật toán Code đã có ở phần phụ lục, ko dán code ở đây
Thay thế bằng sơ đồ khối hoặc giả code
Trình bày các thuật toán và phân tích độ phức tạp của các thuật toán.
Canh
lề phải thẳng hàng
-Hàm Union: Trước hết, chúng ta cần một mảng số nguyên mới được gọi là xếp hạng
[]. Kích thước của mảng này giống như mảng mẹ. Nếu i là đại diện của một tập hợp,
thì rank[i] là chiều cao của cây đại diện cho tập hợp đó. Bây giờ những gì chúng ta
muốn làm là giảm thiểu chiều cao của cây kết quả. Nếu chúng ta đang hợp nhất hai
cây
3
Đồ án lập trình tính toán
(hoặc tập hợp), hãy gọi chúng là trái và phải, sau đó tất cả phụ thuộc vào thứ hạng
của
bên trái và thứ hạng của bên phải.
● Nếu thứ hạng bên trái nhỏ hơn thứ hạng bên phải, thì tốt nhất bạn nên di
chuyển
sang trái dưới bên phải, vì điều đó sẽ không thay đổi thứ hạng bên phải (trong
khi di chuyển sang phải dưới bên trái sẽ làm tăng chiều cao). Theo cách tương
tự, nếu thứ hạng của bên phải nhỏ hơn thứ hạng của bên trái, thì chúng ta nên
di
chuyển sang phải dưới bên trái.
● Nếu các thứ hạng bằng nhau, không quan trọng cây nào đi dưới cây kia, nhưng
thứ hạng của kết quả sẽ luôn lớn hơn thứ hạng của các cây.
-Độ phức tạp thuật toán: Độ cao tối đa của cây là log(n)
Do vậy độ phức tạp của mỗi tạo tác find - union là O( log(n) )
4
Đồ án lập trình tính toán
5
Đồ án lập trình tính toán
6
Đồ án lập trình tính toán
7
Đồ án lập trình tính toán
[2] Độ Phức Tạp Của Thuật Toán Và Lựa Chọn Cách Giải Thuật :
https://codelearn.io/sharing/do-phuc-tap-cua-thuat-toan-va-lua-chon-cach-giai-
thuat#:~:text=Tuy%20
nhi%C3%AAn%20v%E1%BB%9Bi%201%20s%E1%BB%91%20gi%E1%BA%A3i
%20thu%E1%BA%ADt%20s%E1%BA%AFp,ch%E1%BA%A1y%20c%C3%B3%20
th%E1%BB%9Di%20gian%20x%E1%BA%A5p%20x%E1%BB%89%20b%E1%BA
%B1ng%20nhau.
[3] Zvi Galil and Giuseppe F. Italiano : Data structures and algorithms for
disjoint set
union problems : https://dl.acm.org/doi/abs/10.1145/116873.116878
[4] Ashwin Pananjady : The online disjoint set cover problem and its applications
https://ieeexplore.ieee.org/abstract/document/7218497
8
Đồ án lập trình tính toán
PHỤ LỤC
Sinh viên bỏ Code từng phần vào đây.
Code dùng thuật Disjoint-set :
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define ll long long
int Nam , Nu , a, b , c ;
int Parent[1000009] , Rank[1000009] ;
int find(int i) {
if (Parent[i] == i) return i;
else{
int result = find(Parent[i]);
Parent[i] = result;
return result;
}
}
void Union(int i, int j) {
else{
Parent[irep] = jrep;
Rank[jrep]++;
}
}
void Input(){
printf("Nhap so luong cac cap ban be giua cac ban nam : ") ;
10
Đồ án lập trình tính toán
scanf("%d",&a) ;
printf("Nhap moi quan he ban be giua cac ban nam : \n") ;
for (i=0;i<a;i++) {
scanf("%d%d",&tem1,&tem2) ;
Union(tem1,tem2) ;
}
printf("Nhap so luong cac cap ban be giua cac ban nam va cac ban nu : ") ;
scanf("%d",&c ) ;
printf("Nhap moi quan he ban be giua cac ban nam va cac ban nu : \n") ;
for (i=0;i<c;i++) {
scanf("%d%d",&tem1,&tem2) ;
Union(tem1,tem2+Nam) ;
}
}
int groupsize[1000009] ;
void solve(){
int i,j ;
for(i=0;i<=Nam+Nu;i++) groupsize[i] = 0 ;
11
Đồ án lập trình tính toán
for(i=Nam+1;i<=Nam+Nu;i++){
int father = find(i) ;
groupsize[father]++ ;
}
ll res =0 ;
for(i=1;i<=Nam;i++){
res+= Nu-groupsize[find(i)] ;
}
printf("\n\n
_________________________________________________\n\n") ;
printf("So cap sinh vien nam nu co the ghep cap voi nhau : %lld",res) ;
printf("\n\nBan co muon liet ke ra so cap nam nu co the ghep cap voi
nhau khong
? \n") ;
printf("Co : 1 \n") ;
printf("khong : 0 \n") ;
printf("Nhap lua chon : ") ;
int choose = 1 ;
scanf("%d",&choose) ;
if (choose){
printf("\nKet qua :\n") ;
int i , j ;
for (i=1;i<=Nam;i++){
for(j=1;j<=Nu;j++){
if ( find(i)!=find(j+Nam) ){
printf("Nam : %d va Nu : %d \n",i,j);
}
}
}
}
12
Đồ án lập trình tính toán
int main(){
system("COLOR F4");
int luachon = 0 ;
do {
Input() ; solve() ;
13
Đồ án lập trình tính toán
printf("\n\n\n\n\n
==================================================") ;
printf("\n\nBan co muon tiep tuc khong ?\n") ;
printf("Co : 1 \n") ;
printf("khong : 0 \n") ;
printf("Nhap lua chon : ") ;
scanf("%d",&luachon) ;
if(luachon) printf("\n\n\n") ;
}
while(luachon) ;
}
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define ll long long
int Nam , Nu , a, b , c ;
int Path[5000][5000] ;
int check[5000] , visited[5000] ;
void DFS(int u) {
if (visited[u]) return ;
14
Đồ án lập trình tính toán
visited[u] = 1 ;
int i ;
for(i=1;i<=Nam+Nu;i++){
if (Path[u][i]){
check[i] = 1 ;
DFS(i) ;
}
}
}
void Input(){
scanf("%d%d",&Nam,&Nu) ;
int i ,tem1 , tem2 ;
scanf("%d",&a) ;
for (i=0;i<a;i++) {
scanf("%d%d",&tem1,&tem2) ;
Path[tem1][tem2] = Path[tem2][tem1] = 1 ;
}
scanf("%d",&b) ;
for (i=0;i<b;i++) {
scanf("%d%d",&tem1,&tem2) ;
Path[tem1+Nam][tem2+Nam] = Path[tem2+Nam][tem1+Nam] = 1 ;
}
scanf("%d",&c ) ;
for (i=0;i<c;i++) {
scanf("%d%d",&tem1,&tem2) ;
Path[tem1][tem2+Nam] = Path[tem2+Nam][tem1] = 1 ;
}
15
Đồ án lập trình tính toán
}
void solve(){
int i , j , res = 0 ;
for(i=1;i<=Nam;i++){
for(j=1;j<=Nam+Nu;j++) check[j] =
visited[j] = 0 ;
DFS(i) ;
for(j=Nam+1;j<=Nam+Nu;j++){
if(check[j]==0) res++;
}
}
printf("result : %lld",res) ;
}
int main(){
Input() ; solve() ;
}
16