BÀI TOÁN PHẦN MỀM THI CÔNG Adjacency Matrix

 BÀI TOÁN PHẦN MỀM THI CÔNG Adjacency Matrix





//Thi Cong // Adjacency Matrix (Vertices-Vertices) [Directed]

#include <stdio.h>

#define MAX_ELEMENTS 100

//List Structure
typedef int ElementType;
typedef struct {
ElementType data[MAX_ELEMENTS];
int size;
}List;

//Stack Structure
typedef struct
{
    int data[MAX_ELEMENTS];
    int size;
}Stack;

//Queue Structure
typedef struct
{
    int data[MAX_ELEMENTS];
    int front, rear;
}Queue;

/* Init List */

//Make null a list
void make_null_list(List* L) {
    L->size = 0;
}

//Pust List
void push_list(List* L, ElementType x) {
    L->data[L->size] = x;
    L->size++;
}

//Return an element at list
ElementType element_at_list(List* L, int i) {
    return L->data[i-1];
}

//Count amount element in list
int count_list(List* L) {
    return L->size;
}

//Empty a list
int empty_list(List *L)
{
    return L->size == 0;
}

//Copy list
void copy_list(List* L1, List* L2)
{
	int i;
	make_null_list(L1);
	for(i = 1; i <= L2->size; i++)
	{
		push_list(L1, element_at_list(L2, i));
	}
}

/* Init Queue */

//Make null a queue
void make_null_queue(Queue *Q)
{
    Q->front = 0;
    Q->rear = -1;
}

//Push Queue
void push_queue(Queue *Q, int x)
{
    Q->rear++;
    Q->data[Q->rear] = x;
}

//Top Queue
int top_queue(Queue *Q)
{
    return Q->data[Q->front];
}

//Pop Queue
void pop_queue(Queue *Q)
{
    Q->front++;
}

//Empty a Queue
int empty_queue(Queue *Q)
{
    return Q->front>Q->rear;
}

/* Init Stack */

//Make null a stack
void make_null_stack(Stack *S)
{
    S->size = 0;
}

//Push Stack
void push_stack(Stack *S, int x)
{
    S->data[S->size] = x;
    S->size++;
}

//Top stack
int top_stack(Stack *S)
{
    return S->data[S->size - 1];
}

//Pop stack
int pop_stack(Stack *S)
{
    return S->size--;
}

//Empty a stack
int empty_stack(Stack *S)
{
    return S->size == 0;
}

#define MAX 200
#define INFINITY 999999

int d[MAX];
int t[MAX];
int T[MAX];

//Graph Structure
typedef struct
{
    int n;
    int A[MAX][MAX];
}Graph;


/* Init A Basic Graph */

//Init an empty graph
void init_graph(Graph* G, int n)
{
    int i, j;
    G->n = n;
    for(i = 1;  i <= n; i++)
        for(j = 1; j <= n; j++)
            G->A[i][j] = 0;
}

// Add an edge
void add_vecto(Graph *G, int x, int y)
{
    G->A[x][y] = 1;
    G->A[y][x] = -1;
}

//Scan any edge
void scan_vecto_graph(Graph *G, int* work_at, int* start)
{
	int n, u, v, x;
//	freopen("DuAnXayNha.txt","r",stdin);
	scanf("%d", &n);
	init_graph(G, n+2);
	d[n+1] = 0;	
	for(u = 1; u <= n; u++)
	{
		scanf("%d", &d[u]);
		do{
			scanf("%d", &x);
			if (x>0) add_vecto(G,x,u);
		} while(x>0);
	}
	
	//scanf("%d%d", work_at, start);
	for(u = 1; u <= n; u++)
	{
		int deg_neg = 0;
		for(x = 1; x <= n; x++)
			if(G->A[x][u] > 0)
				deg_neg++;
		if(deg_neg == 0 )
			add_vecto(G, n+1, u);
	}
	
	for(u = 1; u <= n; u++)
	{
		int deg_pos = 0;
		for(v = 1; v <= n; v++)
			if(G->A[u][v] > 0)
				deg_pos++;
		if(deg_pos == 0)
			add_vecto(G, u, n+2);
	}
}


//Return IN degree of a vertice
int degree_in(Graph* G, int x)
{
    int y, deg = 0;
    for(y = 1; y <= G->n; y++)
        if(G->A[x][y] < 0)
            deg++;
    return deg;
}

//Has edge
int has_edge(Graph* G, int x, int y)
{
    return ((G->A[x][y] != 0) && (G->A[y][x] != 0)) ? 1 : 0;
}

//Check Adjacency
int check_direction(Graph* G, int x, int y)
{
    return ((G->A[x][y] == 1) && (G->A[y][x] == -1)) ? 1 : 0;
}

//Return Out Vertical Neighbor List ++
List neighbors_out(Graph *G, int x)
{
    int y;
    List list;
    make_null_list(&list);
    for(y = 1; y <= G->n; y++)
        if(check_direction(G, x, y) && has_edge(G, x, y))
        {
            push_list(&list, y);
        }
   return list;
}

void TopoSort(Graph* G, List* L)
{
	int u, d[MAX];
	Queue Q;
	make_null_queue(&Q);
	for(u = 1; u <= G->n; u++)
		d[u] = 0;
	for(u = 1; u <= G->n; u++)
		d[u] = degree_in(G, u);
	for(u = 1; u <= G->n; u++)
		if(d[u] == 0)
			push_queue(&Q, u);
	make_null_list(L);
	while(!empty_queue(&Q))
	{
		int u = top_queue(&Q); pop_queue(&Q);
		push_list(L, u);
		int v;
		for(v = 1; v <= G->n; v++)
		{
			if(has_edge(G, u, v))
			{
				d[v]--;
				if(d[v] == 0)
					push_queue(&Q, v);
			}
		}
	}
}

int min(int a, int b)
{
	return a < b ? a : b;
}

int max(int a, int b)
{
	return a < b ? b : a;
}

void ThiCong(Graph* G, List* L)
{
	int n = G->n - 2;
	t[n+1]=  0;
	int i, v;
	for(i = 2; i <= L->size; i++)
	{
		int u = element_at_list(L, i);
		t[u] = -1;
		for(v = 1; v <= G->n; v++)
			if(check_direction(G, v, u))
				t[u] = max(t[u], t[v] + d[v]);
	}
	
	T[n+2] = t[n+2];
	for(i = L->size - 1; i >= 1; i--){
		int u = element_at_list(L,i);
		T[u] = INFINITY;
		for (v = 1; v <= G->n; v++)
			if(check_direction(G, u, v))
				T[u] = min(T[u], T[v] - d[u]);
	}
}

int main()
{
	int work_at, start;
	Graph dothi;
	scan_vecto_graph(&dothi, &work_at, &start);
	List L;
	TopoSort(&dothi, &L);
	ThiCong(&dothi, &L);
	int j;
	for(j=1;j<=dothi.n;j++)
		if(T[j]==t[j])
			printf("%d\n",j);

	return 0;
}