Simple Graph in Python
I've reviewed your code and I can make the following remarks. I'm only going to review the Graph class for now so lets start:

class Graph:
    """class graph"""


Here the comment is redundant. We know its a Graph and we know its a class. Also note for completeness I like to write class Graph(object)

def __init__(self, v_in):
    """constructor -  takes number of vertices and creates a graph
    with no edges (E = 0) and an empty adjacent lists of vertices"""
    self.V = v_in
    self.E = 0
    self.adj = []
    for i in range(v_in):
        self.adj.append([])


Again the comment is redundant We know its a constructor and what it initializes. However as you may notice the real problem here is not the comment but what it describes. Those V, E, v_in parameters are too short and do not mean anything. If I  were to read the method body and not the class name I wouldn't be able to understand that they denote Vertices and Edges. So a better name for them would be vertices, edges and input_vertices. Note that we use lowercase names for class properties.

def V(self):
    """returns number of vertices"""
    return self.V

def E(self):
    """returns number of edges"""
    return self.E


More redundant notes as we know they return something. However the method names are wrong. Why V and E? And why do they return a number? I would suspect to return a list or an Object that I can query. A better name would be again vertices and edges.

def add_edge(self, v, w):
    """void, adds an edge to the graph"""
    self.adj[v].append(w)
    self.adj[w].append(v)
    self.E += 1

def adj_list(self, v):
    """returns the adjacency lists of the vertex v"""
    return self.adj[v]


That's not too bad although I would remove the void remark and add a better explanation about the input assumptions. For example what happens if  do add_edge(set((1,2,3)), frozenset((4,5,6)))? Traceback error. So its better to specify that it assumes the input is integers.

def __str__(self):
    """to string method, prints the graph"""
    s = str(self.V) + " vertices, " + str(self.E) + " edges\n"
    for v in range(self.V):
        s += str(v) + ": "
        for w in self.adj[v]:
            s += str(w) + " "
        s += "\n"
    return s


Ok nothing wrong here. I would only rename s to output or response so that I understand the meaning.

In general I would say to try to keep the names consistent and meaningful so a reader will not have to guess whats going on.