/* Time limit: 1000ms Memory limit: 256mb ---------------------Copy the following code, complete it and submit--------------------- I, <Your Full Name>, am submitting the assignment for an individual project. I declare that the assignment here submitted is original except for source material explicitly acknowledged, the piece of work, or a part of the piece of work has not been submitted for more than one purpose (i.e. to satisfy the requirements in two different courses) without declaration. I also acknowledge that I am aware of University policy and regulations on honesty in academic work, and of the disciplinary guidelines and procedures applicable to breaches of such policy and regulations, as contained in the University website http://www.cuhk.edu.hk/policy/academichonesty/. It is also understood that assignments without a properly signed declaration by the student concerned will not be graded by the teacher(s). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> typedef enum {ADD = 1, DELETE, QUERY, ERROR_OP} OP; // this linked list has no head or tail, which means that if this list is empty, then it equals NULL struct linkedListNode { int id; struct linkedListNode* next; }; typedef struct linkedListNode* ListNode; ListNode CreateNode(int id) { ListNode node = (ListNode) malloc(sizeof(struct linkedListNode)); node->id = id; node->next = NULL; return node; } // Stack ADT struct stack { int capacity; int* arr; int size; }; typedef struct stack* StackADT; // Create a stack with the given capacity // The stack is empty when it is created StackADT CreateStack(int capacity) { StackADT s = (StackADT) malloc(sizeof(struct stack)); s->arr = (int*) malloc(capacity * sizeof(int)); s->capacity = capacity; s->size = 0; return s; } // Check if the stack is empty // If the stack is empty, return 1, otherwise return 0 int IsEmpty(StackADT s) { return s->size == 0; } // push the value into the stack // If the stack is full, do nothing void Push(StackADT s, int value) { if (s->size < s->capacity) { s->arr[s->size++] = value; } } // Pop the top element of the stack // If the stack is empty, do nothing void Pop(StackADT s) { if (!IsEmpty(s)) { s->size--; } } // Get the top element of the stack int Top(StackADT s) { return s->arr[s->size-1]; } // Free the stack void FreeStack(StackADT s) { free(s->arr); free(s); } // graph // We use array to maintain nodes instead of the hashTables. // For example, G[i] is exactly the adjacency list of the node i struct graph { int n; ListNode* G; }; typedef struct graph* GraphADT; GraphADT CreateGraph(int n) { GraphADT myGraph = (GraphADT) malloc(sizeof(struct graph)); myGraph->n = n; myGraph->G = (ListNode*) malloc(n * sizeof(ListNode)); memset(myGraph->G, 0, n * sizeof(ListNode)); return myGraph; } // Free the graph void FreeGraph(GraphADT myGraph) { for(int i = 0; i < myGraph->n; i++) { ListNode node = myGraph->G[i]; while(node != NULL) { ListNode temp = node; node = node->next; free(temp); } } free(myGraph->G); free(myGraph); } // In our test case, each edge is only added once void AddEdge(GraphADT myGraph, int u, int v) { // WRITE YOUR CODE HERE } // Use DFS to detect cycle in the graph // If the graph is acyclic, return FALSE // If the graph is cyclic, return TRUE bool DetectCycle(GraphADT myGraph) { StackADT myStack = CreateStack(myGraph->n); int* color = (int*) malloc(myGraph->n * sizeof(int)); memset(color, 0, myGraph->n * sizeof(int)); // Color 0 means white, 1 means gray, 2 means black int* discovery_time = (int*) malloc(myGraph->n * sizeof(int)); memset(discovery_time, 0, myGraph->n * sizeof(int)); int* finish_time = (int*) malloc(myGraph->n * sizeof(int)); memset(finish_time, 0, myGraph->n * sizeof(int)); // Remember to free the memory of the stack and the color array // and the discovery_time and finish_time arrays right before returning the answer // FreeStack(myStack); // free(color); // free(discovery_time); // free(finish_time); // WRITE YOUR CODE HERE } int main() { int T, n, m, u, v; scanf("%d", &T); while(T--) { scanf("%d", &n); GraphADT myGraph = CreateGraph(n); scanf("%d", &m); for(int i = 0; i < m; i++) { scanf("%d %d", &u, &v); AddEdge(myGraph, u, v); } int Cycle_Tag = DetectCycle(myGraph); if(Cycle_Tag == 0) { printf("The graph is acyclic.\n"); } else { printf("The graph is cyclic.\n"); } FreeGraph(myGraph); } return 0; } ---------------------------------------End of Code--------------------------------------- ## [Cycle Detection] You are given multiple directed unweighted graphs. For each graph, determine if it is a Directed Acyclic Graph (DAG) or contains a cycle. You also need to implement the Graph ADT with adjacency list. The data guarantee that there is no self-loop in the graph. ### Input The first line contains an integer $T(1\leq T\leq 5)$, representing the number of directed unweighted graphs. For each graph, the first line contains two integers $n, m(1\leq n\leq 100000, 1\leq m \leq 2\times 10^5)$, representing the number of nodes and edges in the graph. The next $m$ lines each contain two integers $u, v(0\leq u, v < n)$, denoting a directed edge from u to v. ### Output For each directed unweighted graph: - Output "The graph is acyclic." if it is a DAG. - Output "The graph is cyclic." if it contains a cycle. ### Example **Input** ``` 3 2 2 1 0 0 1 4 5 0 1 1 2 0 3 1 3 2 3 5 5 1 2 2 4 4 0 0 3 0 2 ``` **Output** ``` The graph is cyclic. The graph is acyclic. The graph is cyclic. ```