Tutorial 9: Graphs
1. Write the BFS and DFS traversals of the graph depicted in the figure below. Start
   both traversals from Node 0 and show contents of Stack/Queue at every step.
2. The number of vertices with odd degree in any graph must be:
   A) Even
   B) Odd
   C) Prime
   D) Composite
   Answer: A) Even
   This is because some of degrees of all vertices is 2E, an even number. Hence number
   of vertices with odd degrees must be even.
3.
     Solution: 12
4. Given two nodes u and v, under what condition can we say that node v is in the subtree
   of node u in the DFS tree of the graph?
       a. d[u]<d[v]<f[v]<f[u]
       b. d[u]<f[u]<d[v]<f[v]
       c. d[u]<d[v] and f[u]<f[v]
       d. d[v]<d[u]<f[u]<f[v]
   Correct Answer: a.
   For node v to be in the subtree of node u, v must be visited after u and finish before u.
5. Consider a graph representing connected cities through edges. There is a city
   which is affected by COVID-19 while all other cities are healthy. Our task is to find
   out the time COVID-19 virus will take to affect all the non-affected cities if it takes
   one unit of time to travel from one city to another. Which one out of BFS and DFS
   can be used?
   Solution: Here one affected city will affect all of its neighbors in one unit of time. This is
   how we know that we need to apply BFS as we need to explore all neighbors of the
   current node first.
   Pseudocode:
   InfectionTime(graph, infectedCity):
           Initialize a queue Q
          Initialize boolean array visited of size INT_MAX to false
          Q.enqueue((infectedCity, 0))
          visited[infectedCity] = True
          maxTime = 0
          //BFS
          While Q is not.empty:
                 currentCity, currentTime = Q.dequeue()
                  maxTime = max(maxTime, currentTime)
                  for neighbor in graph[currentCity]:
                          if visited[neighbor] is false:
                                   visited[neighbor] = True
                                   infectionTime[neighbor] = currentTime + 1
                                   queue.enqueue((neighbor, currentTime + 1))
          Return maxTime
6. David wants to spread a rumor to all n characters in a city. Some characters are
   friends, and any character who hears the rumor will share it with all their friends
   for free. David can pay c[i] gold to start the rumor with any character i, but he
   wants to minimize the total gold spent. What is the minimum amount of gold
   needed to ensure all characters know the rumor?
   Solution: In this problem you are given an undirected graph with weighted vertices. And
   the problem is to calculate the sum of minimum values in every connected component.
   Pseudocode:
   function DFS(v):
           if visited[v] is true:
                    return INT_MAX
          visited[v] = true
          min_cost = c[v]
          for each neighbor in graph[v]:
                  if not visited[neighbor]:
                           min_cost = min(min_cost, DFS(neighbor))
                           visited[neighbor] = true
          return min_cost
// First make a friendship graph, i.e, for all friendship pairs (x, y) add y to adj[x] and add x
to adj[y]
GoldNeeded(adj[], c[]):
         total_cost = 0
         // Explore each component in the graph
         for i = 0 to n-1:
                  if not visited[i]:
                  total_cost += DFS(i) // Add minimum bribe cost for each component
         Return total_cost