给定XY形式的N个依存关系,其中X和Y代表两个不同的任务。依赖关系XY表示形式为Y-> X的依赖关系,即,如果任务Y发生,则任务X将发生,换句话说,任务Y必须首先完成才能启动任务X。还给定M个任务将首先启动。任务是按字典顺序打印将在最后完成的所有任务。请注意,这些任务将仅由大写英文字母表示。
Input: dep[][] = {{A, B}, {C, B}, {D, A}, {D, C}, {B, E}}, tasks[] = {B, C}
Output: A B C D
Task A happens after task B and task D can only happen
after the completion of tasks A or C.
So, the required order is A B C D.
Input: dep[][] = {{Q, P}, {S, Q}, {Q, R}}, tasks[] = {R}
Output: Q R S
方法: DFS可以用来解决问题。形式XY(Y-> X)的依存关系可以表示为图中图中从节点Y到节点X的边。从M个初始节点中的每个初始节点启动DFS,并使用布尔数组将遇到的节点标记为已访问。最后,按字典顺序打印使用DFS覆盖的节点/任务。该方法之所以有效,是因为DFS将以顺序的方式覆盖从初始节点开始的所有节点。
考虑下面的图表,该图表代表了上面的第一个示例:
该图将DFS期间初始任务B和C覆盖的边缘显示为红色。
颜色。这样访问的节点是A,B,C和D。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
#include
#include
using namespace std;
// Graph class represents a directed graph
// using adjacency list representation
class Graph {
// Number of vertices
int V;
// Pointer to an array containing
// adjacency lists
vector* adj;
// Boolean array to mark tasks as visited
bool visited[26];
// A recursive function used by DFS
void DFSUtil(int v);
public:
// Constructor
Graph()
{
// There are only 26 English
// upper case letters
this->V = 26;
adj = new vector[26];
}
// Function to add an edge to the graph
void addEdge(char v, char w);
// DFS traversal of the vertices
// reachable from v
void DFS(char start[], int M);
void printTasks();
};
// Function to add an edge to the graph
void Graph::addEdge(char v, char w)
{
// Add w to v's list
adj[v - 65].push_back(w - 65);
}
void Graph::DFSUtil(int v)
{
// Mark the current node as visited and
// print it
visited[v] = true;
// Recur for all the vertices adjacent
// to this vertex
vector::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i);
}
// DFS traversal of the vertices reachable
// from start nodes
// It uses recursive DFSUtil()
void Graph::DFS(char start[], int M)
{
// Mark all the vertices as not visited
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function
// to print DFS traversal
for (int i = 0; i < M; i++)
DFSUtil(start[i] - 65);
}
// Helper function to print the tasks in
// lexicographical order that are completed
// at the end of the DFS
void Graph::printTasks()
{
for (int i = 0; i < 26; i++) {
if (visited[i])
cout << char(i + 65) << " ";
}
cout << endl;
}
// Driver code
int main()
{
// Create the graph
Graph g;
g.addEdge('B', 'A');
g.addEdge('B', 'C');
g.addEdge('A', 'D');
g.addEdge('C', 'D');
g.addEdge('E', 'B');
// Initial tasks to be run
char start[] = { 'B', 'C' };
int n = sizeof(start) / sizeof(char);
// Start the dfs
g.DFS(start, n);
// Print the tasks that will get finished
g.printTasks();
return 0;
}
Python3
# Python3 implementation of the approach
from collections import defaultdict
# This class represents a directed graph
# using adjacency list representation
class Graph:
# Constructor
def __init__(self):
# Default dictionary to store the graph
self.graph = defaultdict(list)
self.visited = [False]*26
# Function to add an edge to the graph
def addEdge(self, u, v):
self.graph[ord(u)-65].append(ord(v)-65)
# A function used by DFS
def DFSUtil(self, v):
# Mark the current node as visited
# and print it
self.visited[v]= True
# Recur for all the vertices adjacent
# to this vertex
for i in self.graph[v]:
if self.visited[i] == False:
self.DFSUtil(i)
# Function to perform the DFS traversal
# It uses recursive DFSUtil()
def DFS(self, start, M):
# Total vertices
V = len(self.graph)
# Call the recursive helper function
# to print the DFS traversal starting
# from all vertices one by one
for i in range(M):
self.DFSUtil(ord(start[i])-65)
def printOrder(self):
for i in range(26):
if self.visited[i] == True:
print(chr(i + 65), end =" ")
print("\n")
# Driver code
g = Graph()
g.addEdge('B', 'A')
g.addEdge('B', 'C')
g.addEdge('A', 'D')
g.addEdge('C', 'D')
g.addEdge('E', 'B')
g.DFS(['B', 'C'], 2)
g.printOrder()
A B C D
时间复杂度: O(V + E),其中V是图形中节点的数量,E是边或依存关系的数量。在这种情况下,由于V始终为26,因此时间复杂度为O(26 + E)或在最坏的情况下仅为O(E)。
空间复杂度: O(V + E)