<gh_stars>1-10
"""
Created on Tue Nov 27 21:39:19 2018

Taken from Data Structures and Algorithms using Python
"""

class Graph:
    def __init__(self,directed=False):
        self._outgoing = {}
        self._incoming = {} if directed else self._outcoming
        
    def is_directed(self):
        return self._incoming is not self._outgoing
        
    def vertex_count(self):
        return len(self._outgoing)
        
    def vertices(self):
        return self._outgoing.keys()
        
    def edge_count(self):
        total = sum(len(self._outgoing[v]) for v in self._outgoing)
        return total if self.is_directed() else total //2
        
    def edges(self):
        result =set()
        for secondary_map in self._outgoing.value():
            result.update(secondary_map.vaues())
        return result
        
    def get_edge(self,u,v):
        return self._outgoing[u].get(v)
        
    def degree(self,v,outgoing=True):
        adj = self._outgoing if outgoing else self._incoming
        return len(adj[v])
        
    def incident_edges(self,v,outgoing=True):
        adj = self._outgoing if outgoing else self._incoming
        for edge in adj[v].values():
            yield edge
            
    def insert_vertex(self,x=None):
        v = self.Vertex(x)
        self._outgoing[v] = {}
        if self.is_directed():
            self._incoming[v] = {}
        return v
        
    def insert_edge(self,u,v,x=None):
        e=self.Edge(u,v,x)
        self._outgoing[u][v]=e
        self._incoming[u][v]=e

"""
Created on Tue Nov 27 21:39:19 2018

Taken from Data Structures and Algorithms using Python
"""

class Graph:
    def __init__(self,directed=False):
        self._outgoing = {}
        self._incoming = {} if directed else self._outcoming
        
    def is_directed(self):
        return self._incoming is not self._outgoing
        
    def vertex_count(self):
        return len(self._outgoing)
        
    def vertices(self):
        return self._outgoing.keys()
        
    def edge_count(self):
        total = sum(len(self._outgoing[v]) for v in self._outgoing)
        return total if self.is_directed() else total //2
        
    def edges(self):
        result =set()
        for secondary_map in self._outgoing.value():
            result.update(secondary_map.vaues())
        return result
        
    def get_edge(self,u,v):
        return self._outgoing[u].get(v)
        
    def degree(self,v,outgoing=True):
        adj = self._outgoing if outgoing else self._incoming
        return len(adj[v])
        
    def incident_edges(self,v,outgoing=True):
        adj = self._outgoing if outgoing else self._incoming
        for edge in adj[v].values():
            yield edge
            
    def insert_vertex(self,x=None):
        v = self.Vertex(x)
        self._outgoing[v] = {}
        if self.is_directed():
            self._incoming[v] = {}
        return v
        
    def insert_edge(self,u,v,x=None):
        e=self.Edge(u,v,x)
        self._outgoing[u][v]=e
        self._incoming[u][v]=e
Created on Tue Nov 27 21:39:19 2018  Taken from Data Structures and Algorithms using Python