These functions are called on a graph `G`

by calling, e.g., `G.to_undirected()`

. In the code that is given to you, node IDs will be strings.

`to_undirected()`

: converts an directed graph to an undirected version.`add_edge(src, dst)`

: adds an edge between the nodes with IDs`src`

and`dst`

.`add_edges_from(edge_list)`

: like add_edge, but allows multiple edges to be added in a single call`edges()`

: returns a list of edges in the graph. Each edge is a`(src, dst)`

tuple, where`src`

and`dst`

are node IDs.`nodes()`

: returns a list of the node IDs in the graph.`subgraph(node_list)`

: returns a new graph based on the original. Only nodes with IDs in`node_list`

and edges between two nodes in`node_list`

will survive.`delete_node(node_id)`

: deletes the node with ID`node_id`

from the graph. Any edges with`node_id`

as an endpoint will also be removed.`edge_boundary(node_list_a, node_list_b)`

: returns a list of edges which have one endpoint in`node_list_a`

and the other endpoint in`node_list_b`

.`get_edge(src, dst)`

: when working with an weighted graph, returns the weight associated with the edge from`src`

to`dst`

.

`networkx.component.strongly_connected_components(G)`

: On a DiGraph`G`

, returns a list of strongly connected components. Each strongly connected component is represented as a list of node IDs.

`if v in G:`

checks if node v is in graph G`if (u,v) in G.edges():`

checks if an edge from u to v exists in G`G[u]`

returns a list of nodes reachable from node u.