void DFSint v{ cout... Viết hàm có tên là int TPLT_DFSint a[ ] [ ] trên C/C++ tìm số thành phần liên thông của đồ ị G = được biểu diễn dưới dạng ma trận kề a[ ] [ ] bằng thcách sử dụng
Trang 1Họ tên: Đoàn Thị Trà My
MSV: B21DCAT134
Nhóm:
1 Viết hàm có tên là DFS(int u) trên C/C++ mô tả thuật toán duyệt theo chiều sâu các đỉnh của đồ thị G = <V, E> được biểu diễn dưới dạng ma trận kề a[ ] [ ]
void DFS(int v){
cout << v << " "; // tham dinh u
int u;
chuaxet[v]= 0; // danh dau la dinh v da duoc duyet
for(u=1; u<=n; u++){
if(a[v][u]==1 && chuaxet[u])
DFS(u);
}
}
Trang 22 Viết hàm có tên là BFS( int u) trên C/C++ mô tả uật toán duyệt theo chiều rộng các th đỉnh của đồ ị G = <V, E> được biểu diễn dưới dạng ma trận kề a[][] th
int n, u; // n đỉnh va duyet tu dinh u
int a[1000][1000] = {0};
bool visited[1000]; // v[i] = 1 -> đỉnh i đã được duyệt
int QUEUE[1000];
void BFS(int i){
int u,dauQ, cuoiQ;
dauQ=1; cuoiQ=1; QUEUE[cuoiQ]=i;
visited[i]= 1; // danh dau la da tham
/* thiết lập hàng đợi với đỉnh đầu là i*/
while(dauQ<=cuoiQ){
u=QUEUE[dauQ];// lấy đỉnh u ra ỏi queue.kh
cout<< u << " ";
dauQ=dauQ+1; /* duyệt đỉnh đầu hàng đợi*/
for(int j=1; j<=n;j++){
if(a[u][j]==1 && !visited[j]){
cuoiQ=cuoiQ+1;
QUEUE[cuoiQ]=j;
visited[j]=1;
}
}
}
}
Trang 33 Viết hàm có tên là int TPLT_DFS(int a[ ] [ ]) trên C/C++ tìm số thành phần liên thông của đồ ị G = <V, E> được biểu diễn dưới dạng ma trận kề a[ ] [ ] bằng th cách sử dụng hàm DFS(int u) đã biết mô tả thuật toán duyệt theo chiều sâu các đỉnh của đồ ị th G
int n, ans = 0; // n đỉnh và ans: số tplt của đồ thị
int a[1000][1000] = {0};
bool chuaxet[1000]; // ban đầu cho hết bằng 1 nghĩa là tất cả đỉnh chưa được duyệt
void DFS(int a[][1000], int n, int v, bool chuaxet[]){
int u;
chuaxet[v]= false;
for(u=1; u<=n; u++){
if(a[v][u]==1 && chuaxet[u])
DFS(a,n, u, chuaxet);
}
}
int TPLT_dfs(int a[][1000]){
ans = 0;
for(int i = 1; i<= n; i++){
if(chuaxet[i] == 1) {
ans++;
DFS(a, n, i, chuaxet);
}
}
return ans;
}
Trang 44 Viết hàm có tên là int TPLT_BFS(int a[ ] [ ]) trên C/C++ tìm số thành phần liên thông của đồ ị G = <V, E> th đư ợc biểu diễn dưới dạng ma trận kề a[ ] [ ] bằng cách sử dụng hàm BFS(int u) đã biết mô tả thuật toán duyệt theo chiều rộng các đỉnh của đồ ị th
G
int n, ans = 0; // n đỉnh và ans: số tplt của đồ thị
int a[1000][1000] = {0};
bool visited[1000]; // v[i] = 1 -> đỉnh i đã được duyệt
int QUEUE[1000];
void BFS(int i, bool visited[], int QUEUE[]){
int u,dauQ, cuoiQ;
dauQ=1; cuoiQ=1;QUEUE[cuoiQ]=i;
visited[i]= 1; // danh dau la da tham
/* thiết lập hàng đợi với đỉnh đầu là i*/
while(dauQ<=cuoiQ){
u=QUEUE[dauQ]; // lấy đỉnh u ra khỏi queue
dauQ=dauQ+1; /* duyệt đỉnh đầu hàng đợi*/
for(int j=1; j<=n;j++){
if(a[u][j]==1 && !visited[j]){
cuoiQ=cuoiQ+1;
QUEUE[cuoiQ]=j;
visited[j]=1;
}
}
}
}
int TPLT_bfs(int a[][1000]){
ans = 0;
for(int i = 1; i<= n; i++){
if(visited[i] == 0) {
ans++;
BFS(i, visited, QUEUE);
}
}
return ans;
}
Trang 55 Viết hàm có tên là T_DFS(int a[ ] [ ]) trên C/C++ tìm cây khung T[] của đồ ị th G
= <V, E> được biểu diễn dưới dạng ma trận kề a[][] bằng cách sử dụng hàm DFS(int u) đã biết mô tả thuật toán duyệt theo chiều sâu các đỉnh của đồ ị th G
int a[100][100], n, u, vs[100], e[100];
void Dfs(int u) {
int v;
vs[u]= 1;
for (v= 1; v<=n; v++)
if (vs[v]==0 && a[u][v]==1){
e[v]= u;
Dfs(v);
}
}
void T_Dfs(int a[][100]) {
int u =1; // lấy đỉnh đầu là 1;
int v;
for (v= 1; v<=n; v++) vs[v] = 0;
Dfs(u);
int dem= 0;
for (v= 1; v<=n; v++) if (vs[v] ==1) dem++;
if (dem == n) {
for (v= 1; v<=n; v++)
if (e[v] != 0) cout << e[v] << " "<< v << endl;
} else
cout << "Khong co Cay khung";
}
Trang 66 Viết hàm có tên là T_BFS(int a[ ] [ ]) trên C/C++ tìm cây khung T[] của đồ ị th G
= <V, E> được biểu diễn dưới dạng ma trận kề ][] bằng cách sử dụng hàm a[ BFS(int u) đã biết mô tả thuật toán duyệt theo chiều rộng các đỉnh của đồ thị G
const int MAX = 100; // giả sử số đỉnh của đồ ị là 100th
int n; // số đỉnh của đồ thị
int T[MAX]; // mảng lưu cây khung T
bool visited[MAX]; // mảng đánh dấu các đỉnh đã thăm
queue<int> Q; // hàng đợi lưu các đỉnh
void BFS(int u, int a[][MAX]){
visited[u] = true; // đánh dấu đỉnh u đã thăm
Q.push(u); // đưa u vào hàng đợi
while (!Q.empty()){
int v = Q.front(); // lấy đỉnh đầu tiên ra khỏi hàng đợi
Q.pop();
// duyệt các đỉnh kề v của đỉnh v
for (int i = 1; i <= n; i++){
if (a[v][i] > 0 && !visited[i]) {// nếu có cạnh (v, i) và đỉnh i chưa thăm
visited[i] = true; // đánh dấu đỉnh i đã thăm
Q.push(i); // đưa i vào hàng đợi
T[i] = v; // lưu đỉnh cha của i trong cây khung T
}
}
}
}
void T_BFS(int a[][MAX]){
memset(visited, false, sizeof(visited)); // ởi tạkh o m ảng visited toàn false
memset(T, 0, sizeof(T)); // khởi tạo mảng T toàn 0
BFS(1, a); // bắt đầu duyệt đồ ị từ đỉnh 1th
// hiển thị cây khung T
cout << "Cay khung T:" << endl;
for (int i = 2; i <= n; i++) { // bỏ qua đỉnh 1 vì là đỉnh bắt đầu của cây khung
cout << T[i] << "-" << i << endl;
}
}
Trang 77 Viết hàm có tên là EULER(int a[ ] [ ]) trên C/C++ tìm chu trình/đường đi Euler CE[ ] của đồ ị G = <V, E> được biểu diễn dưới dạng ma trận kề a[][], biết rằng th
G là đồ ị Euler/nửa Euler th
const int MAX = 1005;
int n;
int a[MAX][MAX];
vector<int> path;
void DFS(int u) {
for (int v = 1; v <= n; v++) {
if (a[u][v] != 0) {
a[u][v] =a[v][u]=0; // Xóa cạnh (u, v)
DFS(v);
}
}
path.push_back(u); // Thêm đỉnh u vào đường đi
}
vector<int> EULER(int a[][MAX]) {
// Tìm số đỉnh có bậc lẻ
int cnt = 0, start = 1;
for (int i = 1; i <= n; i++) {
int deg = 0;
for (int j = 1; j <= n; j++) {
deg += a[i][j];
}
if (deg % 2 != 0) {
cnt++;
start = i;
}
}
// Nếu số đỉnh có bậc lẻ lớn hơn 2, đồ ị không là đồ ị Euler th th
if (cnt > 2) {
cout << "Khong co chu trinh/duong di Euler!" << endl;
return vector<int>();
}
// Tạo stack S và đưa đỉnh start vào S
stack<int> S;
S.push(start);
Trang 8// Duyệt đồ ị bằng thuật toán DFS và tìm chu trình Euler th while (!S.empty()) {
int u = S.top();
bool found = false;
for (int v = 1; v <= n && !found; v++) {
if (a[u][v] != 0) {
found = true;
S.push(v);
a[u][v] a[v][u]= 0= ; // Xóa cạnh (u, v) }
}
if (!found) {
S.pop();
path.push_back(u); // Thêm đỉnh u vào đường đi }
}
// Đảo ngược đường đi và trả về chu trình Euler vector<int> cycle(path.rbegin(), path.rend()); return cycle;
}
Trang 98 Viết hàm có tên là DIJKSTRA(int u) trên C/C++ tìm đư ờng đi ngắn nhất d[v] xuất phát từ đỉnh u đến các đỉnh v của đồ ị G = <V, E> được biểu diễn dướ th i dạng ma trận trọng số a[ ] [ ]
const int MAX = 1005; // giới hạn số đỉnh của đồ thị
int n; // số đỉnh của đồ thị
int a[MAX][MAX]; // ma trận trọng số của đồ thị
int d[MAX]; // mảng d[v] chứa độ dài đường đi ngắn nhất từ đỉnh u đến đỉnh v
bool visited[MAX]; // mảng visited để đánh dấu các đỉnh đã được duyệt trong thuật toán Dijkstra
void DIJKSTRA(int u) {
// Khởi tạo độ dài đường đi ngắn nhất từ đỉnh u đến các đỉnh v
for (int v = 1; v <= n; v++) {
d[v] = INT_MAX;
}
d[u] = 0;
// Tạo hàng đợi ưu tiên để lưu trữ các đỉnh và khoảng cách tương ứng
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; pq.push(make_pair(0, u));
while (!pq.empty()) {
int du = pq.top().first;
int u = pq.top().second;
pq.pop();
if (visited[u]) {
continue;
}
visited[u] = true;
for (int v = 1; v <= n; v++) {
if (a[u][v] != 0 && !visited[v]) {
if (d[v] > du + a[u][v]) {
d[v] = du + a[u][v];
pq.push(make_pair(d[v], v));
}
}
}
}
}
Trang 109 Viết hàm có tên là FLOYD(int a[ ] [ ]) trên C/C++ tìm đường đi ngắn nhất d[ ] [ ] giữa các cặp đỉnh của đồ ị G = <V, E> được biểu diễn dưới dạng ma trận trọng th
số a[ ] [ ]
const int INF = 1e9; // Giá trị vô cùng
const int MAXN = 1005;
void FLOYD(int a[][MAXN], int d[][MAXN], int n) {
// Khởi tạo ma trận đường đi
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
d[i][j] = a[i][j];
}
}
// Duyệt qua tất cả các đỉnh trung gian
for (int k = 1; k <= n; k++) {
// Duyệt qua tất cả các cặp đỉnh (i, j)
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// Nếu tồn tại đường đi ngắn hơn từ i đến j đi qua đỉnh k
if (d[i][k] < INF && d[k][j] < INF && d[i][j] > d[i][k] + d[k][j]) { // Cập nhật giá trị đường đi ngắn nhất từ i đến j
d[i][j] = d[i][k] + d[k][j];
}
}
}
}
}
Trang 1110 Viết hàm có tên là PRIM(int a[ ] [ ], int u) trên C/C++ tìm cây khung T[ ] nhỏ nhất bắt đầu tại đỉnh u của đồ ị G = <V, E> được biểu diễn dưới dạng ma trậ th n trọng số a[ ] [ ] bằng cách sử dụng thuật toán Prim
const int INF = 1e9;
const int MAX = 1000;
int PRIM(int a[MAX][MAX], int u) {
int V = sizeof(a[0])/sizeof(a[0][0]); // lấy số đỉnh của đồ thị
int key[V]; // key[i] lưu giá trị nhỏ nhất để đi từ T đến i
int parent[V]; // lưu cây khung nhỏ nhất đã tìm được
bool mstSet[V]; // mstSet[i] = true nếu đỉnh i đã được đưa vào cây khung nhỏ nhất
// khởi tạo giá trị cho key và mstSet
for (int i = 0; i < V; i++) {
key[i] = INF;
mstSet[i] = false;
}
key[u] = 0; // giá trị key của đỉnh xuất phát bằng 0
parent[u] = -1; // đỉnh xuất phát không có parent
for (int count = 0; count < V - 1; count++) {
// Tìm đỉnh có key nhỏ nhất chưa được chọn vào cây khung nhỏ nhất
int minKey = INF, minIndex;
for (int v = 0; v < V; v++) {
if (mstSet[v] == false && key[v] < minKey) {
minKey = key[v];
minIndex = v;
}
}
// Thêm đỉnh đã tìm được vào cây khung nhỏ nhất
mstSet[minIndex] = true;
// Cập nhật giá trị key và parent của các đỉnh kề với đỉnh đã thêm vào cây khung nhỏ nhất for (int v = 0; v < V; v++) {
if (a[minIndex][v] && mstSet[v] == false && a[minIndex][v] < key[v]) { parent[v] = minIndex;
key[v] = a[minIndex][v];
}
}
}
// In cây khung nhỏ ất tìm được nh
cout << "Cay khung nho nhat:\n";
for (int i = 0; i < V; i++) {
if (parent[i] != -1) {
cout << parent[i] << " - " << i << " " << a[i][parent[i]] << "\n";
}
}
}
Trang 1211 Viết hàm có tên là KRUSKAL(int a[ ] [ ]) trên C/C++ tìm cây khung T[ ] nhỏ nhất của đồ ị G = <V, E> được biểu diễn dưới dạng ma trận trọng số a[ ] [ ] th bằng cách sử dụng thuật toán Kruskal
int n, m;
const int MAXN = 100;
int parent[MAXN];
int sz[MAXN];
struct Edge {
int u, v, w; //u: đỉnh đầu ; v: đỉnh cuối; w: trọng số
};
void make_set(){
for (int i= 1; i<= n; i++){
parent[i] = i;
sz[i] = 1;
}
}
int find(int v){
if( v== parent[v]) return v;
return parent[v] = find(parent[v]);
}
bool merge(int x, int y) {
x = find(x);
y = find(y);
if(x== y) return 0; // ko the gop x, y vao voi nhau
if (sz[x] < sz[y]) swap(x, y);
parent[y] = x;
sz[x] += sz[y];
return true;
}
vector<Edge> canh;
void inp(){ // input
cin >> n >> m;
for(int i = 0; i < m ; i++){
int x, y, w; cin>> x >> y >> w;
Edge e ;
e.u = x; e.v = y; e.w = w;
canh.push_back(e);
}
}
Trang 13bool cmp(Edge a, Edge b) {
return a.w < b.w;
}
void kruskal(){
// Tao cay khung
vector<Edge> mst;
int d = 0;
// sort danh sach canh theo chieu dai tang dan
sort(canh.begin(), canh.end(), cmp);
// lap
for(int i = 0; i< m; i++){
if(mst.size() == n-1) break;
Edge e = canh[i]; // chon e la canh nho nhat
if(merge(e.u, e.v)){
mst.push_back(e);
d+= e.w;
}
}
// tra ve ket qua
if(mst.size() != n-1){
cout << "Do thi khong lien thong" << endl;
}
else{
cout << "Do dai cuc tieu cua cay khung: " << d << endl; for (auto it : mst) {
cout << it.u << " " << it.v << " " << it.w << endl; }
}
}
Trang 1412 Viết chương trình hoàn chỉ nh tìm luồng cực đại f[][] trên mạng G = <V, E> đượ c biểu diễn dưới dạng ma trận trọng số c[ ] [ ] với đỉnh phát s và đỉnh thu t bằng cách sử dụng thuật toán đường tăng luồ ng dựa trên Ford-Fulkerson :
Yêu cầu :
(1) Nhập ma trận trọng số ểu diễn G từ tệp DT.INP ; với s= 1 ; t= n bi ;
(2) Tìm luồng cực đại f ;
(3) Xuất kết quả ra tệp DT.OUT :
- Dòng đầu ghi Val(f) ;
- N dòng sau ghi f[i][j] ;
#include <bits/stdc++.h>
#include <cstring>
#include <queue>
#include <limits.h>
#define MAX 100
using namespace std;
int n, s = 1, t; // đỉnh phát s = 1
int c[MAX][MAX], f[MAX][MAX], trace[MAX];
int res = 0; // giá trị ồng cực đạilu
bool bfs() { // tìm đường tăng luồng bằng BFS
queue<int> q;
q.push(s);
memset(trace, 0, sizeof(trace)); // khởi tạo trace
trace[s] = s;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v = 1; v <= n; v++) {
if (trace[v] == 0 && f[u][v] < c[u][v]) {
Trang 15q.push(v);
trace[v] = u;
if (v == t) return true;
}
}
}
return false;
}
void augment_path() { // cập nhật luồng trên đường tăng luồng int u = t, v;
int delta = INT_MAX;
while (u != s) {
v = trace[u];
delta = min(delta, c[v][u] - f[v][u]);
u = v;
}
u = t;
while (u != s) {
v = trace[u];
f[v][u] += delta;
f[u][v] -= delta;
u = v;
}
res += delta; // cập nhật giá trị ồng cực đạilu
}
void ford_fulkerson() { // thuật toán Ford-Fulkerson while (bfs()) {
augment_path();