C - Graph

Codes

  • #include <memory.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NEIGHBORS_INITIAL_CAP 4  // Initial capacity for neighbors array
    
    /**
     * @struct Node
     * @brief Represents a node in the graph
     */
    typedef struct {
      int id;             // Node identifier
      int *neighbors;     // Dynamic array of neighboring node IDs
      int neighborsSize;  // Current number of neighbors
      int neighborsCap;   // Current capacity of neighbors array
    } Node;
    
    /**
     * @struct Graph
     * @brief Represents the entire graph
     */
    typedef struct {
      Node *nodes;    // Array of all nodes
      int nodesSize;  // Number of nodes in the graph
    } Graph;
    
    /**
     * @struct Guard
     * @brief Represents a guard with position and movement range
     */
    typedef struct {
      int node;  // Node where the guard is located
      int h;     // Movement range of the guard
    } Guard;
    
    /**
     * @struct Result
     * @brief Stores the result of the problem
     */
    typedef struct {
      int G;   // Number of nodes that can be protected
      int *v;  // Array of protected node IDs
    } Result;
    
    /**
     * @brief Initialize a node with given ID
     * @param node Pointer to the node to initialize
     * @param id ID to assign to the node
     */
    void init_node(Node *node, int id) {
      node->id = id;
      node->neighborsSize = 0;
      node->neighborsCap = NEIGHBORS_INITIAL_CAP;
      node->neighbors = calloc(node->neighborsCap, sizeof(int));
      if (node->neighbors == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
    }
    
    /**
     * @brief Free memory allocated for a node
     * @param node Pointer to the node to free
     */
    void free_node(Node *node) { free(node->neighbors); }
    
    /**
     * @brief Create a new graph with specified number of nodes
     * @param nodesSize Number of nodes in the graph
     * @return Pointer to the created graph
     */
    Graph *get_graph(int nodesSize) {
      Graph *graph = malloc(sizeof(Graph));
      if (graph == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
      graph->nodesSize = nodesSize;
      graph->nodes = calloc(nodesSize, sizeof(Node));
      if (graph->nodes == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
      for (int i = 0; i < nodesSize; ++i) {
        init_node(&graph->nodes[i], i);
      }
      return graph;
    }
    
    /**
     * @brief Free memory allocated for a graph
     * @param graph Pointer to the graph to free
     */
    void free_graph(Graph *graph) {
      for (int i = 0; i < graph->nodesSize; i++) {
        free_node(&graph->nodes[i]);
      }
      free(graph->nodes);
    }
    
    /**
     * @brief Add a neighbor to a node's neighbor list
     * @param node Pointer to the node
     * @param neighbor ID of the neighbor to add
     */
    void insert_neighbor(Node *node, int neighbor) {
      // Double capacity if needed
      if (node->neighborsSize == node->neighborsCap) {
        node->neighborsCap *= 2;
        node->neighbors =
            realloc(node->neighbors, node->neighborsCap * sizeof(int));
        if (node->neighbors == NULL) {
          fprintf(stderr, "Memory allocation failed\n");
          exit(1);
        }
      }
      node->neighbors[node->neighborsSize++] = neighbor;
    }
    
    /**
     * @brief Add an undirected edge between two nodes in the graph
     * @param graph Pointer to the graph
     * @param u First node ID
     * @param v Second node ID
     */
    void add_edge(Graph *graph, int u, int v) {
      if (u >= graph->nodesSize || v >= graph->nodesSize) {
        fprintf(stderr, "Invalid node id\n");
        exit(1);
      }
      insert_neighbor(&graph->nodes[u], v);
      insert_neighbor(&graph->nodes[v], u);
    }
    
    /**
     * @brief Comparison function for qsort to sort node IDs
     */
    int cmp_result(const void *a, const void *b) { return *(int *)a - *(int *)b; }
    
    /**
     * @struct Heap
     * @brief Max-heap implementation for priority queue of guards
     */
    typedef struct {
      Guard *data;  // Array of guards
      int size;     // Current number of elements
      int cap;      // Current capacity
    } Heap;
    
    /**
     * @brief Get the index of the left child in the heap
     * @param x Index of the parent
     * @return Index of the left child
     */
    int heap_left_son(int x) { return 2 * x + 1; }
    
    /**
     * @brief Get the index of the right child in the heap
     * @param x Index of the parent
     * @return Index of the right child
     */
    int heap_right_son(int x) { return 2 * x + 2; }
    
    /**
     * @brief Get the index of the parent in the heap
     * @param x Index of the child
     * @return Index of the parent
     */
    int heap_parent(int x) { return (x - 1) / 2; }
    
    /**
     * @brief Swap two guards in the heap
     * @param a Pointer to first guard
     * @param b Pointer to second guard
     */
    void swap(Guard *a, Guard *b) {
      Guard tmp = *a;
      *a = *b;
      *b = tmp;
    }
    
    /**
     * @brief Move an element up the heap to maintain heap property
     * @param heap Pointer to the heap
     * @param x Index of the element to sift up
     */
    void sift_up(Heap *heap, int x) {
      while (x > 0) {
        int parent = heap_parent(x);
        if (heap->data[x].h > heap->data[parent].h) {
          swap(&heap->data[x], &heap->data[parent]);
          x = parent;
        } else {
          break;
        }
      }
    }
    
    /**
     * @brief Move an element down the heap to maintain heap property
     * @param heap Pointer to the heap
     * @param x Index of the element to sift down
     */
    void sift_down(Heap *heap, int x) {
      int left = heap_left_son(x);
      int right = heap_right_son(x);
    
      int largest = x;
      // Find the largest among the node and its children
      if (left < heap->size && heap->data[left].h > heap->data[largest].h) {
        largest = left;
      }
      if (right < heap->size && heap->data[right].h > heap->data[largest].h) {
        largest = right;
      }
    
      // If largest is not the current node, swap and continue sifting down
      if (largest != x) {
        swap(&heap->data[x], &heap->data[largest]);
        sift_down(heap, largest);
      }
    }
    
    /**
     * @brief Convert an array into a heap
     * @param heap Pointer to the heap
     */
    void heapify(Heap *heap) {
      // Start from the last non-leaf node and sift down each node
      for (int i = heap->size / 2 - 1; i >= 0; --i) {
        sift_down(heap, i);
      }
    }
    
    /**
     * @brief Add a guard to the heap
     * @param heap Pointer to the heap
     * @param guard Guard to add
     */
    void heap_push(Heap *heap, Guard guard) {
      // Double capacity if needed
      if (heap->size == heap->cap) {
        heap->cap *= 2;
        heap->data = realloc(heap->data, heap->cap * sizeof(Guard));
        if (heap->data == NULL) {
          fprintf(stderr, "Memory allocation failed\n");
          exit(1);
        }
      }
      heap->data[heap->size++] = guard;
      sift_up(heap, heap->size - 1);
    }
    
    /**
     * @brief Remove and return the guard with highest h value
     * @param heap Pointer to the heap
     * @return Guard with highest h value
     */
    Guard heap_pop(Heap *heap) {
      Guard result = heap->data[0];
      heap->data[0] = heap->data[--heap->size];
      sift_down(heap, 0);
      return result;
    }
    
    /**
     * @brief Create a new heap from an array of guards
     * @param data Array of guards
     * @param k Number of guards
     * @return Pointer to the created heap
     */
    Heap *heap_build(Guard *data, int k) {
      Heap *heap = malloc(sizeof(Heap));
      if (heap == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
      heap->data = calloc(k, sizeof(Guard));
      if (heap->data == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
      memcpy(heap->data, data, k * sizeof(Guard));
      heap->size = k;
      heap->cap = k;
      heapify(heap);
      return heap;
    }
    
    /**
     * @brief Free memory allocated for a heap
     * @param heap Pointer to the heap to free
     */
    void heap_free(Heap *heap) { free(heap->data); }
    
    /**
     * @brief Check if the heap is empty
     * @param heap Pointer to the heap
     * @return true if empty, false otherwise
     */
    bool heap_empty(Heap *heap) { return heap->size == 0; }
    
    /**
     * @brief Solve the problem using a modified Dijkstra's algorithm
     * @param n Number of nodes
     * @param m Number of edges
     * @param k Number of guards
     * @param graph Pointer to the graph
     * @param guards Array of guards
     * @return Result containing protected nodes
     */
    Result solve(int n, int m, int k, Graph *graph, Guard *guards) {
      // Create a max-heap of guards prioritized by movement range
      Heap *heap = heap_build(guards, k);
    
      // Track visited nodes
      bool *visited = calloc(n, sizeof(bool));
      memset(visited, 0, n * sizeof(bool));
    
      // Process guards in order of decreasing movement range
      while (!heap_empty(heap)) {
        Guard guard = heap_pop(heap);
        if (visited[guard.node]) {
          continue;  // Skip if node already visited
        }
        visited[guard.node] = true;
        if (guard.h == 0) {
          continue;  // Guard can't move further
        }
    
        // Explore neighbors with reduced movement range
        for (int i = 0; i < graph->nodes[guard.node].neighborsSize; ++i) {
          int neighbor = graph->nodes[guard.node].neighbors[i];
          if (!visited[neighbor]) {
            heap_push(heap, (Guard){neighbor, guard.h - 1});
          }
        }
      }
    
      heap_free(heap);
    
      // Collect results
      Result result;
      result.G = 0;
      // Count protected nodes
      for (int i = 0; i < n; ++i) {
        if (visited[i]) {
          result.G++;
        }
      }
    
      // Store protected node IDs
      result.v = calloc(result.G, sizeof(int));
      for (int i = 0, j = 0; i < n; ++i) {
        if (visited[i]) {
          result.v[j++] = i;
        }
      }
    
      free(visited);
      return result;
    }
    
    /**
     * @brief Main function to read input, solve the problem, and output results
     */
    int main() {
      int n, m, k;
      scanf("%d%d%d", &n, &m, &k);
    
      // Create graph with n nodes
      Graph *graph = get_graph(n);
    
      // Read m edges
      for (int i = 0; i < m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        add_edge(graph, u - 1, v - 1);  // Convert to 0-indexed
      }
    
      // Read k guards
      Guard *guards = calloc(k, sizeof(Guard));
      if (guards == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
      for (int i = 0; i < k; ++i) {
        scanf("%d%d", &guards[i].node, &guards[i].h);
        guards[i].node--;  // Convert to 0-indexed
      }
    
      // Solve the problem
      Result result = solve(n, m, k, graph, guards);
    
      // Sort the result for consistent output
      qsort(result.v, result.G, sizeof(int), cmp_result);
    
      // Print results (convert back to 1-indexed)
      printf("%d\n", result.G);
      for (int i = 0; i < result.G; ++i) {
        printf("%d ", result.v[i] + 1);
      }
      printf("\n");
    
      // Clean up
      free(result.v);
      free(guards);
      free_graph(graph);
      free(graph);
      return 0;
    }
    
  • #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <vector>
    
    struct Guard {
      int pos;
      int power;
      Guard(int p, int pow) : pos(p), power(pow) {}
    
      int getPos() const { return pos; }
      int getPower() const { return power; }
    };
    
    struct GuardComparator {
      bool operator()(const Guard& g1, const Guard& g2) {
        return g1.getPower() <
               g2.getPower();  // Min-heap by default, so we reverse it
      }
    };
    
    class Solution {
     public:
      /**
       * @param n: Number of nodes
       * @param m: Number of edges
       * @param k: Number of security guards
       * @param edges: a vector of vector of integers where each element is a pair
       * that represent an edge
       * @param guards: a vector of vector of integers where each element is a pair
       * representing the position and guarding power
       * @return: return the list of nodes that are covered by guards
       */
      static std::vector<int> solve(int n, int m, int k,
                                    std::vector<std::vector<int>>& edges,
                                    std::vector<std::vector<int>>& guards) {
        std::vector<std::vector<int>> adj(n + 1);
        for (int i = 0; i < m; ++i) {
          adj[edges[i][0]].push_back(edges[i][1]);
          adj[edges[i][1]].push_back(edges[i][0]);
        }
        std::priority_queue<Guard, std::vector<Guard>, GuardComparator> pq;
        std::vector<bool> covered(n + 1, false);
        for (int i = 0; i < k; ++i) {
          pq.push(Guard(guards[i][0], guards[i][1]));
        }
        while (!pq.empty()) {
          Guard g = pq.top();
          pq.pop();
          int power = g.getPower();
          int pos = g.getPos();
          if (covered[pos]) continue;
          covered[pos] = true;
          if (power == 0) continue;
          for (int next : adj[pos]) {
            if (!covered[next]) {
              pq.push(Guard(next, power - 1));
            }
          }
        }
        std::vector<int> ans;
        for (int i = 1; i <= n; ++i) {
          if (covered[i]) {
            ans.push_back(i);
          }
        }
        return ans;
      }
    };
    
    int main() {
      int n, m, k;
      std::cin >> n >> m >> k;
      std::vector<std::vector<int>> edges(m, std::vector<int>(2));
      for (int i = 0; i < m; ++i) {
        std::cin >> edges[i][0] >> edges[i][1];
      }
      std::vector<std::vector<int>> guards(k, std::vector<int>(2));
      for (int i = 0; i < k; ++i) {
        std::cin >> guards[i][0] >> guards[i][1];
      }
      std::vector<int> ans = Solution::solve(n, m, k, edges, guards);
      std::cout << ans.size() << std::endl;
      for (int node : ans) {
        std::cout << node << " ";
      }
      std::cout << std::endl;
      return 0;
    }
    
  • import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.List;
    import java.util.PriorityQueue;
    import java.util.Scanner;
    
    class Guard {
      int pos;
      int power;
      Guard(int pos, int power) {
        this.pos = pos;
        this.power = power;
      }
    
      public int getPos() {
        return this.pos;
      }
    
      public int getPower() {
        return this.power;
      }
    }
    
    class Graph {
      List<List<Integer>> adj;
    
      Graph(int n) {
        adj = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
          adj.add(new ArrayList<>());
        }
      }
    
      public void addEdge(int u, int v) {
        adj.get(u).add(v);
        adj.get(v).add(u);
      }
    
      public List<Integer> getListOfAdjecentNodes(int u) {
        return adj.get(u);
      }
    }
    
    class Main {
      /**
       * @param n: Number of nodes
       * @param m: Number of edges
       * @param k: number of security guards
       * @param edges: a list of list of integers where each element is a list of two integers that
       *     represent an edge
       * @param guards: a list of list of integers where each element is a list of two integers
       *     represent the position and guarding power
       * @return: return the maximum achieveable fullness
       */
      public static List<Integer> solve(int n, int m, int k, int edges[][], int guards[][]) {
        // Implement your solution here
    
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
          adj.add(new ArrayList<>());
        }
        for (int i = 0; i < m; i++) {
          adj.get(edges[i][0]).add(edges[i][1]);
          adj.get(edges[i][1]).add(edges[i][0]);
        }
    
        PriorityQueue<Guard> pq = new PriorityQueue<>(Comparator.comparing(Guard::getPower).reversed());
        boolean[] covered = new boolean[n + 1];
        Arrays.fill(covered, false);
        for (int i = 0; i < k; i++) {
          pq.add(new Guard(guards[i][0], guards[i][1]));
        }
    
        while (!pq.isEmpty()) {
          Guard g = pq.poll();
          int power = g.getPower();
          int pos = g.getPos();
          if (covered[pos])
            continue;
          covered[pos] = true;
          if (power == 0)
            continue;
          for (int i = 0; i < adj.get(pos).size(); i++) {
            int next = adj.get(pos).get(i);
            if (!covered[next]) {
              pq.add(new Guard(next, power - 1));
            }
          }
        }
    
        List<Integer> ans = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
          if (covered[i])
            ans.add(i);
        }
        return ans;
      }
    
      // ALTERNATIVE
      /**
       * @param n: Number of nodes
       * @param m: Number of edges
       * @param k: number of security guards
       * @param graphs: an object of the class Graph
       * @param guards: a list of object of the class Guard
       * @return: return the list of nodes that are covered by the guards
       */
      // public static List<Integer> solve(int n, int m, int k, int edges[][], int guards[][]) {
      // }
      public static List<Integer> solve(int n, int m, int k, Graph graph, Guard[] guards) {
        // Implement your solution here
    
        PriorityQueue<Guard> pq = new PriorityQueue<>(Comparator.comparing(Guard::getPower).reversed());
        boolean[] covered = new boolean[n + 1];
        Arrays.fill(covered, false);
        for (int i = 0; i < k; i++) {
          pq.add(guards[i]);
        }
    
        while (!pq.isEmpty()) {
          Guard g = pq.poll();
          int power = g.getPower();
          int pos = g.getPos();
          if (covered[pos])
            continue;
          covered[pos] = true;
          if (power == 0)
            continue;
          List<Integer> adjacentNode = graph.getListOfAdjecentNodes(pos);
          for (int i = 0; i < adjacentNode.size(); i++) {
            int next = adjacentNode.get(i);
            if (!covered[next]) {
              pq.add(new Guard(next, power - 1));
            }
          }
        }
    
        List<Integer> ans = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
          if (covered[i])
            ans.add(i);
        }
        return ans;
      }
    
      public static void main(String[] args) throws java.lang.Exception {
        Scanner input = new Scanner(System.in);
    
        int n = input.nextInt();
        int m = input.nextInt();
        int k = input.nextInt();
        int edges[][] = new int[m][2];
        Graph graph = new Graph(n);
    
        for (int i = 0; i < m; i++) {
          edges[i][0] = input.nextInt();
          edges[i][1] = input.nextInt();
          graph.addEdge(edges[i][0], edges[i][1]);
        }
    
        Guard[] guards = new Guard[k];
        int guardsInArray[][] = new int[k][2];
    
        for (int i = 0; i < k; i++) {
          guardsInArray[i][0] = input.nextInt();
          guardsInArray[i][1] = input.nextInt();
          guards[i] = new Guard(guardsInArray[i][0], guardsInArray[i][1]);
        }
    
        List<Integer> ans1 = solve(n, m, k, edges, guardsInArray);
        List<Integer> ans2 = solve(n, m, k, graph, guards);
        List<Integer> ans = new ArrayList<>();
    
        if (ans1.size() != 0)
          ans = ans1;
        if (ans2.size() != 0)
          ans = ans2;
    
        System.out.println(ans.size());
        for (int i = 0; i < ans.size(); i++) {
          System.out.print(ans.get(i) + " ");
        }
        System.out.println();
        input.close();
      }
    }
    
  • from dataclasses import dataclass, field
    
    
    @dataclass(order=True)
    class GuardedNode:
        """
        A dataclass representing a node with a guard.
    
        Attributes:
            node (int): The index of the node in the graph (0-indexed internally).
            h (int): The strength of the guard at this node (how far it can protect).
    
        Note:
            The comparison is based only on the guard strength (h) for heap operations.
        """
    
        node: int = field(compare=False)
        h: int
    
    
    class Heap:
        """
        A max-heap implementation specialized for GuardedNode objects.
    
        This heap prioritizes nodes with higher guard strength values.
        """
    
        def __init__(self, guarded_nodes: list[GuardedNode]):
            """
            Initialize a heap with a list of GuardedNode objects.
    
            Args:
                guarded_nodes: List of GuardedNode objects to initialize the heap.
            """
            self.heap = guarded_nodes
            for i in range(self.n // 2 - 1, -1, -1):
                self.sift_down(i)
    
        def __len__(self):
            """Return the number of elements in the heap."""
            return len(self.heap)
    
        @property
        def n(self):
            """Property that returns the size of the heap."""
            return len(self)
    
        def push(self, node: GuardedNode):
            """
            Add a new GuardedNode to the heap.
    
            Args:
                node: The GuardedNode to add to the heap.
            """
            self.heap.append(node)
            self.sift_up(self.n - 1)
    
        def empty(self):
            """
            Check if the heap is empty.
    
            Returns:
                bool: True if the heap is empty, False otherwise.
            """
            return self.n == 0
    
        def pop(self) -> GuardedNode:
            """
            Remove and return the GuardedNode with the highest guard strength.
    
            Returns:
                GuardedNode: The node with the highest guard strength.
    
            Raises:
                IndexError: If the heap is empty.
            """
            if self.empty():
                raise IndexError("pop from an empty heap")
    
            self.heap[0], self.heap[-1] = self.heap[-1], self.heap[0]
            node = self.heap.pop()
    
            if not self.empty():
                self.sift_down(0)
    
            return node
    
        def sift_up(self, x: int):
            """
            Move a node up the heap to maintain the heap property.
    
            Args:
                x: The index of the node to sift up.
            """
            while x > 0:
                parent = Heap.parent(x)
                if self.heap[x].h > self.heap[parent].h:
                    self.heap[x], self.heap[parent] = self.heap[parent], self.heap[x]
                    x = parent
                else:
                    break
    
        def sift_down(self, x: int):
            """
            Move a node down the heap to maintain the heap property.
    
            Args:
                x: The index of the node to sift down.
            """
            left = Heap.left_son(x)
            right = Heap.right_son(x)
    
            largest = x
            if left < self.n and self.heap[left].h > self.heap[largest].h:
                largest = left
            if right < self.n and self.heap[right].h > self.heap[largest].h:
                largest = right
    
            if largest != x:
                self.heap[x], self.heap[largest] = self.heap[largest], self.heap[x]
                self.sift_down(largest)
    
        @staticmethod
        def left_son(x: int):
            """
            Calculate the index of the left child of a node.
    
            Args:
                x: The index of the parent node.
    
            Returns:
                int: The index of the left child.
            """
            return 2 * x + 1
    
        @staticmethod
        def right_son(x: int):
            """
            Calculate the index of the right child of a node.
    
            Args:
                x: The index of the parent node.
    
            Returns:
                int: The index of the right child.
            """
            return 2 * x + 2
    
        @staticmethod
        def parent(x: int):
            """
            Calculate the index of the parent of a node.
    
            Args:
                x: The index of the child node.
    
            Returns:
                int: The index of the parent.
            """
            return (x - 1) // 2
    
    
    class Solution:
        @staticmethod
        def solve(
            n: int,
            m: int,
            k: int,
            edges: list[tuple[int, int]],
            guards: list[tuple[int, int]],
        ) -> set[int]:
            """
            Args:
                n: Number of nodes in the graph (1-indexed).
                m: Number of edges in the graph.
                k: Number of guards.
                edges: List of edges as (u, v) pairs where u and v are 1-indexed node IDs.
                guards: List of guards as (p, h) pairs where p is the 1-indexed node ID
                       and h is the protection range.
    
            Returns:
                set[int]: A set of 1-indexed node IDs that are protected.
            """
            e = [[] for _ in range(n)]
            for u, v in edges:
                e[u - 1].append(v - 1)
                e[v - 1].append(u - 1)
            guarded_nodes = [GuardedNode(p - 1, h) for p, h in guards]
            heap = Heap(guarded_nodes)
            result = set()
            while heap:
                current = heap.pop()
                if current.node in result:
                    continue
                result.add(current.node)
                if current.h == 0:
                    continue
                for neighbor in e[current.node]:
                    if neighbor not in result:
                        heap.push(GuardedNode(neighbor, current.h - 1))
            return {node + 1 for node in result}
    
    
    if __name__ == "__main__":
        """
        Main entry point for the program.
    
        Reads input in the following format:
        - First line: three integers n, m, k (number of nodes, edges, and guards)
        - Next m lines: two integers u, v representing an edge
        - Next k lines: two integers p, h representing a guard at node p with strength h
    
        Outputs:
        - First line: the number of protected nodes
        - Second line: the sorted list of protected node IDs
        """
        n, m, k = map(int, input().split())
        edges = []
        for _ in range(m):
            u, v = map(int, input().split())
            edges.append((u, v))
        guarded_nodes = []
        for _ in range(k):
            p, h = map(int, input().split())
            guarded_nodes.append((p, h))
        result = Solution.solve(n, m, k, edges, guarded_nodes)
        print(len(result))
        print(*sorted(result))