// 演算法 / Algorithm:
// 1) 建鄰接表，從 k 做迭代式 DFS，標記所有可達（=可疑）節點。
//    Build adjacency list, iterative DFS from k, mark all reachable (=suspicious) nodes.
// 2) 掃每條邊：若有「非可疑 a 呼叫可疑 b」，則無法移除，回傳全部節點。
//    Scan edges: if any non-suspicious a calls suspicious b, removal fails -> return all.
// 3) 否則回傳所有非可疑節點。 Otherwise return every non-suspicious node.

#include <stdlib.h>   // malloc / calloc / free / realloc

int* remainingMethods(int n, int k, int** invocations, int invocationsSize,
                      int* invocationsColSize, int* returnSize) {
    // head[v] 存節點 v 的第一條邊的索引；-1 代表沒有邊（鏈式前向星）
    // head[v] = index of v's first edge; -1 means no edge (a linked adjacency list)
    int* head = (int*)malloc(sizeof(int) * n);          // 每個節點一個表頭 / one head per node
    for (int i = 0; i < n; i++) head[i] = -1;           // 初始化為 -1 / init to "no edge"

    // to[] 存邊的終點，nxt[] 存「同一起點的下一條邊」的索引，形成鏈結串列
    // to[] = edge's destination; nxt[] = index of next edge from same source (linked list)
    int m = invocationsSize;                            // 邊的數量 / number of edges
    int* to  = (int*)malloc(sizeof(int) * (m > 0 ? m : 1));  // 避免 malloc(0) / avoid malloc(0)
    int* nxt = (int*)malloc(sizeof(int) * (m > 0 ? m : 1));

    for (int e = 0; e < m; e++) {                       // 逐條邊加入鄰接表 / add each edge
        int a = invocations[e][0];                      // 起點 a / source a
        int b = invocations[e][1];                      // 終點 b / destination b
        to[e]  = b;                                     // 這條邊指向 b / this edge points to b
        nxt[e] = head[a];                               // 接到 a 原本的鏈頭 / link to a's old head
        head[a] = e;                                    // 新的鏈頭是 e / a's new head is edge e
    }

    // suspicious[v]：v 是否可疑（從 k 可達）。calloc 會把記憶體全設為 0(=false)
    // suspicious[v]: is v reachable from k? calloc zero-fills memory (0 = false)
    char* suspicious = (char*)calloc(n, sizeof(char));

    // 用陣列當作明確的堆疊做迭代式 DFS，避免遞迴太深導致 stack overflow
    // Use an array as an explicit stack for iterative DFS (avoids deep-recursion overflow)
    int* stack = (int*)malloc(sizeof(int) * n);
    int top = 0;                                        // top 指向堆疊下一個空位 / next free slot
    stack[top++] = k;                                   // 把起點 k 推入堆疊 / push start node k
    suspicious[k] = 1;                                  // k 本身就是可疑的 / k itself is suspicious

    while (top > 0) {                                   // 堆疊還有東西就繼續 / while stack not empty
        int u = stack[--top];                           // 彈出一個節點 u / pop a node u
        for (int e = head[u]; e != -1; e = nxt[e]) {    // 走過 u 的每條邊 / iterate u's edges
            int v = to[e];                              // 這條邊的終點 v / edge destination v
            if (!suspicious[v]) {                        // v 還沒被標記過才處理 / only if unvisited
                suspicious[v] = 1;                       // 標記 v 為可疑 / mark v suspicious
                stack[top++] = v;                        // 推入堆疊稍後展開 / push v to expand later
            }
        }
    }

    // 檢查是否有「外部呼叫內部」：非可疑的 a 呼叫可疑的 b
    // Check for any outside->inside call: non-suspicious a invoking suspicious b
    int canRemove = 1;                                  // 先假設可以移除 / assume removable
    for (int e = 0; e < m; e++) {
        int a = invocations[e][0];
        int b = invocations[e][1];
        if (!suspicious[a] && suspicious[b]) {           // a 在外、b 在內 = 違規 / outside calls inside
            canRemove = 0;                               // 不能移除任何東西 / cannot remove anything
            break;                                       // 找到一個就夠了 / one is enough, stop
        }
    }

    // 配置結果陣列，最多 n 個元素 / allocate result array, at most n elements
    int* ans = (int*)malloc(sizeof(int) * n);
    int cnt = 0;                                        // 已放入結果的數量 / count written so far

    if (canRemove) {                                    // 可以移除 -> 只留非可疑節點 / keep non-suspicious
        for (int i = 0; i < n; i++)
            if (!suspicious[i]) ans[cnt++] = i;
    } else {                                            // 不能移除 -> 全部保留 / keep everything
        for (int i = 0; i < n; i++)
            ans[cnt++] = i;
    }

    *returnSize = cnt;                                  // 透過指標回傳陣列長度 / report length via pointer

    free(head); free(to); free(nxt);                    // 釋放暫時記憶體，避免 memory leak
    free(suspicious); free(stack);                      // free temporary memory to avoid leaks
    return ans;                                         // 回傳結果陣列 / return the answer array
}
