📌  相关文章
📜  根据依赖关系在最后打印完成的任务

📅  最后修改于: 2021-10-25 05:08:20             🧑  作者: Mango

给定XY形式的N 个依赖项,其中 X 和 Y 代表两个不同的任务。依赖关系 XY 表示形式Y -> X 的依赖关系,即,如果任务 Y 发生,则任务 X 将发生,换句话说,任务 Y 必须首先完成才能启动任务 X。也给定 M 个将首先启动的任务。任务是按字典顺序打印将在末尾完成的所有任务。请注意,任务将仅由大写英文字母表示。

处理方法:可以使用DFS来解决问题。 XY (Y -> X)形式的依赖关系可以表示为图中从节点Y到节点X的边。从 M 个初始节点中的每一个启动 DFS,并使用布尔数组将遇到的节点标记为已访问。最后,按字典顺序打印使用 DFS 覆盖的节点/任务。该方法有效,因为 DFS 将按顺序覆盖从初始节点开始的所有节点。

考虑下图,它代表了上面的第一个示例:

该图将初始任务 B 和 C 在 DFS 期间覆盖的边缘显示为红色
颜色。这样访问的节点是 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)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。