KIỂM TRA LIÊN THÔNG MẠNH
// CT175 - Lý thuy?t d? th? (B? môn KHMT - Khoa CNTT & TT, DHCT)
// B1809362 - Truong Qu?c K?
// Gi?i thu?t d?a trên ma tr?n liên thu?c (Ð?nh - cung) cho d? th? có hu?ng và vô hu?ng
#include <stdio.h>
#define MAX_VERTICES 100
#define MAX_EDGES 500
#define MAX_ELEMENTS 100
#define white 0
#define black 1
#define gray 2
int mark[MAX_VERTICES];
int parent[MAX_VERTICES];
int color[MAX_VERTICES];
int cycle;
// C?u trúc List
typedef int ElementType;
typedef struct {
ElementType data[MAX_ELEMENTS];
int size;
} List;
// C?u trúc Stack
typedef struct
{
int data[MAX_ELEMENTS];
int size;
}Stack;
// C?u trúc Queue
typedef struct
{
int data[MAX_ELEMENTS];
int front, rear;
}Queue;
// C?u trúc Graph
typedef struct
{
int n, m;
int A[MAX_VERTICES][MAX_EDGES];
}Graph;
// Cài d?t Queue
void make_null_queue(Queue *Q)
{
Q->front = 0;
Q->rear = -1;
}
void push_queue(Queue *Q, int x)
{
Q->rear++;
Q->data[Q->rear] = x;
}
int top_queue(Queue *Q)
{
return Q->data[Q->front];
}
void pop_queue(Queue *Q)
{
Q->front++;
}
int empty_queue(Queue *Q)
{
return Q->front>Q->rear;
}
// Cài d?t danh sách
void make_null_list(List* L) {
L->size = 0;
}
void push_list(List* L, ElementType x) {
L->data[L->size] = x;
L->size++;
}
ElementType element_at_list(List* L, int i) {
return L->data[i-1];
}
int count_list(List* L) {
return L->size;
}
int empty_list(List *L)
{
return L->size == 0;
}
// Cài d?t Stack
void make_null_stack(Stack *S)
{
S->size = 0;
}
void push_stack(Stack *S, int x)
{
S->data[S->size] = x;
S->size++;
}
int top_stack(Stack *S)
{
return S->data[S->size - 1];
}
int pop_stack(Stack *S)
{
return S->size--;
}
int empty_stack(Stack *S)
{
return S->size == 0;
}
// Bi?n h? tr? liên thông m?nh (d? th? có hu?ng)
int num[MAX_VERTICES];
int min_num[MAX_VERTICES];
Stack S;
int on_stack[MAX_VERTICES];
int k = 0;
// T?o d? th? r?ng
void init_graph(Graph *G, int n, int m)
{
int i, j;
G->n = n;
G->m = m;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= m; j++)
{
G->A[i][j] = 0;
}
}
}
// Thêm cung vô hu?ng
void add_edge(Graph *G, int e, int x, int y)
{
G->A[x][e] = 1;
G->A[y][e] = 1;
}
// Thêm cung có hu?ng
void add_vecto(Graph *G, int e, int x, int y)
{
G->A[x][e] = 1;
G->A[y][e] = -1;
}
// Nh?p danh sách cung vô hu?ng t? bàn phím
void scan_graph(Graph *G)
{
int n, m, u, v, e;
scanf("%d%d", &n, &m);
init_graph(G, n, m);
for (e = 1; e <= m; e++) {
scanf("%d%d", &u, &v);
add_edge(G, e, u, v);
}
}
// Nh?p danh sách cung có hu?ng t? bàn phím
void scan_vecto_graph(Graph *G)
{
int n, m, u, v, e;
scanf("%d%d", &n, &m);
init_graph(G, n, m);
for (e = 1; e <= m; e++) {
scanf("%d%d", &u, &v);
add_vecto(G, e, u, v);
}
}
// Nh?p tu?n t? ma tr?n
void scan_obo_graph(Graph *G)
{
int n, m;
scanf("%d%d", &n, &m);
init_graph(G, n, m);
int i, j;
G->n = n;
G->m = m;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= m; j++)
{
scanf("%d", &G->A[i][j]);
}
}
}
// In ma tr?n d? th?
void print_graph(Graph *G)
{
int i, j;
printf("\nMatrix %dx%d: \n", G->n, G->m);
for(i = 1; i <= G->n; i++)
{
for(j = 1; j <= G->m; j++)
{
printf("%d ", G->A[i][j]);
}
printf("\n");
}
}
// Ð?c d? th? t? file (vô hu?ng) dùng add_vecto() n?u có hu?ng
void read_graph(FILE *F, Graph *G)
{
int e, u ,v, m, n;
fscanf(F, "%d%d", &n, &m);
init_graph(G, n, m);
for(e = 1; e <= m; e++)
{
fscanf(F, "%d%d", &u, &v);
add_edge(G, e, u, v);
}
}
// Ki?m tra k?
int check_adj(Graph *G, int x, int y)
{
int j, temp;
for(j = 1; j <= G->m; j++)
{
if((G->A[x][j] > 0) && (G->A[y][j] > 0))
{
if(x == y)
temp = 0;
else
{
temp = 1;
break;
}
}
else
temp = 0;
}
return temp;
}
// Ki?m tra k? có hu?ng
int check_adj_io(Graph *G, int x, int y)
{
int j, temp;
for(j = 1; j <= G->m; j++)
{
if(((G->A[x][j] > 0) && (G->A[y][j] > 0)) || ((G->A[x][j] == 1) && (G->A[y][j] == -1)))
{
if(x == y)
temp = 0;
else
{
temp = 1;
break;
}
}
else if((G->A[x][j] == -1) && (G->A[y][j] == -1))
temp = 1;
else
temp = 0;
}
return temp;
}
// B?c ra d?nh x
int degree_out(Graph *G, int x)
{
int e, deg = 0;
for(e = 1; e <= G->m; e++)
{
if(G->A[x][e] == 1)
deg++;
}
return deg;
}
// B?c vào d?nh x
int degree_in(Graph *G, int x)
{
int e, deg = 0;
for(e = 1; e <= G->m; e++)
{
if(G->A[x][e] == -1)
deg++;
}
return deg;
}
// Tr? v? danh sách k? d?nh x vô hu?ng
List neighbors(Graph *G, int x)
{
int y;
List list;
make_null_list(&list);
for(y = 1; y <= G->n; y++)
if(check_adj(G, x, y))
{
push_list(&list, y);
}
return list;
}
// Tr? v? danh sách k? d?nh x có hu?ng
List neighbors_io(Graph *G, int x)
{
int y;
List list;
make_null_list(&list);
for(y = 1; y <= G->n; y++)
if(check_adj_io(G, x, y))
{
push_list(&list, y);
}
return list;
}
// T?o l?i các d?nh chua du?c dánh d?u
void reset_mark(Graph *G)
{
int i;
for(i = 1; i <= G->n; i++)
mark[i] = 0;
}
// Xoá các d?nh cha
void reset_parent(Graph *G)
{
int i;
for(i = 1; i <= G->n; i++)
parent[i] = -1;
}
// Duy?t theo chi?u sâu, vô hu?ng
void DFS(Graph *G, int x)
{
Stack S;
make_null_stack(&S);
push_stack(&S, x);
parent[x] = 0;
int i;
while(!empty_stack(&S))
{
int u = top_stack(&S);
pop_stack(&S);
if(mark[u] == 1)
continue;
printf("Duyet: %d\n", u);
mark[u] = 1;
List L = neighbors(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
if(mark[v] == 0)
{
push_stack(&S, v);
parent[v] = u;
}
}
}
}
// Duy?t theo chi?u r?ng, vô hu?ng
void BFS(Graph *G, int x)
{
Queue Q;
make_null_queue(&Q);
push_queue(&Q, x);
parent[x] = 0;
int i;
while(!empty_queue(&Q))
{
int u = top_queue(&Q);
pop_queue(&Q);
if(mark[u] == 1)
continue;
printf("Duyet: %d\n", u);
mark[u] = 1;
List L = neighbors(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
if(mark[v] == 0)
{
push_queue(&Q, v);
parent[v] = u;
}
}
}
}
// Duy?t theo chi?u sâu d? quy, vô hu?ng
void DFS_Recursion(Graph *G, int u, int p)
{
int i;
if(mark[u] == 1)
return;
printf("Duyet: %d\n", u);
parent[u] = p;
mark[u] = 1;
List L = neighbors(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
DFS_Recursion(G, v, u);
}
}
// Duy?t d? quy u
void traversal(Graph *G, int u)
{
int i;
if(mark[u] == 1)
return;
mark[u] = 1;
List L = neighbors(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
traversal(G, v);
}
}
// Ð?m s? thành ph?n liên thông c?a d? th? vô hu?ng
int count_connected_components(Graph *G)
{
int i, cmt;
for(i = 1; i <= G->n; i++)
if(mark[i] == 0)
{
traversal(G, i);
cmt++;
}
return cmt;
}
// Duy?t d? quy u (chu trình vô hu?ng)
void traversal_cycle(Graph *G, int u, int p)
{
int i;
color[u] = gray;
if(mark[u] == 1)
return;
mark[u] = 1;
List L = neighbors(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
if(v == p) continue;
if(color[v] == gray)
{
cycle = 1;
return;
}
if(color[v] == white)
traversal_cycle(G, v, u);
}
color[u] = black;
}
// Ki?m tra chu trình d? th? vô hu?ng
int contains_cycle(Graph *G)
{
int i;
for(i = 1; i <= G->n; i++)
color[i] = white;
cycle = 0;
for(i = 1; i <= G->n; i++)
if(color[i] == white)
traversal_cycle(G, i, 0);
return cycle;
}
// Duy?t d? quy u (chu trình có hu?ng)
void traversal_cycle_io(Graph *G, int u)
{
int i;
color[u] = gray;
if(mark[u] == 1)
return;
mark[u] = 1;
List L = neighbors_io(G, u);
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
if(color[v] == gray)
{
cycle = 1;
return;
}
if(color[v] == white)
traversal_cycle_io(G, v);
}
color[u] = black;
}
// Ki?m tra chu trình d? th? có hu?ng
int contains_cycle_io(Graph *G)
{
int i;
for(i = 1; i <= G->n; i++)
color[i] = white;
cycle = 0;
for(i = 1; i <= G->n; i++)
if(color[i] == white)
traversal_cycle_io(G, i);
return cycle;
}
// Tìm giá tr? nh? nh?t
int min(int a, int b)
{
int result;
if(a < b)
result = a;
else
result = b;
return result;
}
int str = 0;
// Tìm s? thành ph?n liên thông m?nh
void strong_connect(Graph *G, int u)
{
k++;
num[u] = min_num[u] = k;
push_stack(&S, u);
on_stack[u] = 1;
List L = neighbors_io(G, u);
int i;
for(i = 1; i <= L.size; i++)
{
int v = element_at_list(&L, i);
if(num[v] < 0)
{
strong_connect(G, v);
min_num[u] = min(min_num[u], min_num[v]);
}
else if (on_stack[v])
min_num[u] = min(min_num[u], num[v]);
}
//printf("min_num[%d] = %d\n", u, min_num[u]);
if(num[u] == min_num[u])
{
//printf("%d la dinh khop\n", u);
int w;
do
{
w = top_stack(&S);
pop_stack(&S);
on_stack[w] = 0;
} while (w != u);
str++;
}
}
void check_strong_connect(Graph *G)
{
int v;
make_null_stack(&S);
k = 1;
for(v = 1; v <= G->n; v++)
{
num[v] = -1;
on_stack[v] = 0;
}
for(v = 1; v <= G->n; v++)
if(num[v] == -1)
strong_connect(G, v);
//printf("%d\n", str);
}
int main()
{
// T?o m?t d? th?
Graph dothi;
// Bi?n l?p
// int i, u;
// Các thao tác
scan_vecto_graph(&dothi);
// Ðánh d?u các d?nh chua duy?t
reset_mark(&dothi);
reset_parent(&dothi);
// Duy?t d? th?
//for(i = 1; i <= dothi.n; i++)
// if(mark[i] == 0)
// DFS(&dothi, i);
check_strong_connect(&dothi);
printf("%d", str);
return 0;
}
