Como menciona Yuval, la estructura de datos es importante aquí. Trataré de dar una solución para algunos de los tipos de listas de adyacencia:
- Lista de bordes entrantes : para cada nodo, hay una lista de vértices desde los cuales hay un borde entrante a este nodo. Simplemente puede escanear todos los vértices y verificar si el tamaño de su lista de adyacencia es0 0 o no. Un tamaño0 0lista significa que no hay bordes entrantes, por lo que el nodo es una fuente o está desconectado. Suponiendo un gráfico conectado, este escaneo de cada vértice le dará una lista de todas las fuentes (o puede detenerse después de encontrar una) enO ( | VEl | )tiempo - lineal en el número de vértices .
- Lista de bordes salientes : para cada nodo, hay una lista de vértices a los que hay un borde dirigido desde este nodo. Mantenga una cadena de bits con cada bit que represente un vértice, inicializado a 0. Comenzando desde el primer nodo, comience a escanear su lista en busca de vértices a los que hay un borde saliente de este. Cada uno de estos nodos (vecinos) no puede ser una fuente, por lo tanto, siga configurando su bit correspondiente en la cadena de bits. Al final, todos los vértices cuyos bits correspondientes aún están sin definir son los vértices de origen. Puede hacer esto en un tiempo lineal en el tamaño del gráfico :O ( | VEl | + | miEl | ).
- Ambas listas juntas : para cada vértice, hay una lista mixta de vértices que tienen un borde hacia o desde este vértice, con algún otro atributo que indica cuál de los dos es realmente el caso. El enfoque es similar al 2 anterior, con la adición de que cualquier borde entrante descarta inmediatamente el vértice actual (y puede marcar su conjunto de bits). A diferencia del punto 2, donde debe atravesar todos los vértices, aquí puede encontrar alguna fuente antes. Si no te detienes, tendrás todas las fuentes. Para ambos casos, el tiempo es nuevamente lineal en el tamaño del gráfico :O ( | VEl | + | miEl | ).
- Ambas listas por separado : simplemente elija la lista de borde entrante y siga 1.
Como nota al margen, si elegir la estructura de datos está en sus manos, es posible que desee analizar qué operaciones pretende realizar y con qué frecuencia, y elegir una estructura de datos adecuada.
Editar: para el caso 1, si tiene un dag donde el número de fuentes es muy pequeño en comparación conEl | VEl |(por ejemplo, en un árbol con una fuente), y donde la distancia promedio desde cualquier vértice a una fuente es pequeña en comparación conEl | VEl | y solo desea una fuente única, puede usar un algoritmo más rápido en promedio (aunque la peor complejidad asintótica será la misma). Seleccione cualquier vértice al azar, y vaya a cualquiera de sus padres (de la lista de borde entrante), y luego a su padre y así sucesivamente, hasta llegar a un nodo que no tiene padre - una fuente. Esta pequeña ganancia de eficiencia es para tipos muy limitados de gráficos con un algoritmo un poco más complejo.