📌  相关文章
📜  尽量减少需要在学生之间分发的笔记数量

📅  最后修改于: 2021-09-06 06:29:48             🧑  作者: Mango

给定一个数组arr[]N 个字符串组成,表示班级中学生的姓名,另一个数组P[][2]使得P[i][0]喜欢P[i][1] ,任务是找到要在课堂上分发的最少笔记数量,以便只有在学生直接或间接喜欢另一个学生时才能共享笔记。

例子:

方法:在给定条件下生成关系图后,可以通过在有向图中找到强连通分量的数量来解决给定问题。请按照以下步骤解决问题:

  • 创建一个哈希图,比如M将学生的姓名映射到他们各自的索引值。
  • 使用变量i遍历数组A并将映射M中的每个字符串A[i]映射到值i
  • 迭代数组P中的所有对,并为每一对从 HashMap 中获取相应的值, M并在它们之间创建有向边。
  • 在遍历所有对之后,形成具有N个顶点和M个边的有向图。
  • 创建一个空栈S ,并执行图的 DFS 遍历:
    • 创建一个递归函数,该函数采用节点的索引和访问过的数组。
    • 将当前节点标记为已访问并遍历所有相邻和未标记的节点,并使用相邻节点的索引调用递归函数。
    • 遍历当前节点的所有邻居后,将当前节点压入堆栈S
  • 反转所有边的方向以获得构造图的转置。
  • 迭代直到栈S不为空,执行以下步骤:
    • 存储栈顶元素S 在变量V 中并将其从堆栈S 中弹出。
    • 从节点V作为源执行 DFS 遍历。
    • 更新连接组件的数量并将计数存储在变量 sat cnt 中
  • 完成以上步骤后,打印cnt的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
  
// Sturture of class Graph
class Graph {
  
    // No. of vertices
    int V;
  
    // An array of adjacency lists
    list* adj;
  
    // Function that fills the stack
    // with the vertices v
    void fillOrder(int v, bool visited[],
                   stack& Stack);
  
    // Recursive function to perform
    // the DFS starting from v
    void DFSUtil(int v, bool visited[]);
  
public:
    Graph(int V);
    void addEdge(int v, int w);
  
    // Function to count the number of
    // strongly connected components
    void countSCCs();
  
    // Function that returns reverse
    // (or transpose) of the graph
    Graph getTranspose();
};
  
// Constructor of the Graph
Graph::Graph(int V)
{
    this->V = V;
    adj = new list[V];
}
  
// Recursive function to perform the
// DFS  starting from v
void Graph::DFSUtil(int v, bool visited[])
{
    // Mark the current node as visited
    visited[v] = true;
  
    // Recurr for all the vertices
    // adjacent to this vertex
    list::iterator i;
  
    for (i = adj[v].begin();
         i != adj[v].end(); ++i) {
        if (!visited[*i])
            DFSUtil(*i, visited);
    }
}
  
// Function to return the reverse
// (or transpose) of the graph
Graph Graph::getTranspose()
{
    Graph g(V);
    for (int v = 0; v < V; v++) {
  
        // Recurr for all the vertices
        // adjacent to this vertex
        list::iterator i;
  
        for (i = adj[v].begin();
             i != adj[v].end(); ++i) {
            g.adj[*i].push_back(v);
        }
    }
    return g;
}
  
// Function to add an edge
void Graph::addEdge(int v, int w)
{
    // Add w to v’s list
    adj[v].push_back(w);
}
  
// Function to fill the stack with
// the vertices during DFS traversal
void Graph::fillOrder(int v, bool visited[],
                      stack& Stack)
{
    // Mark the current node as visited
    visited[v] = true;
  
    // Recurr for all the vertices
    // adjacent to this vertex
    list::iterator i;
  
    for (i = adj[v].begin();
         i != adj[v].end(); ++i) {
        if (!visited[*i])
            fillOrder(*i, visited, Stack);
    }
  
    // All vertices reachable from
    // the node v are processed
    // Update the stack
    Stack.push(v);
}
  
// Function that counts the strongly
// connected components in the graph
void Graph::countSCCs()
{
    stack Stack;
  
    // Mark all the vertices as not
    // visited (For first DFS)
    bool* visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;
  
    // Fill vertices in the stack
    // according to their finishing
    // time
    for (int i = 0; i < V; i++) {
        // Vertex i is not visited
        if (visited[i] == false)
            fillOrder(i, visited, Stack);
    }
  
    // Create a reversed graph
    Graph gr = getTranspose();
  
    // Mark all the vertices as
    // not visited (For second DFS)
    for (int i = 0; i < V; i++)
        visited[i] = false;
    int cnt = 0;
  
    // Now process all vertices in
    // order defined by Stack
    while (Stack.empty() == false) {
  
        // Pop a vertex from stack
        int v = Stack.top();
        Stack.pop();
  
        // Get the strongly connected
        // component of the popped
        // vertex
        if (visited[v] == false) {
  
            gr.DFSUtil(v, visited);
            cnt++;
        }
    }
  
    // Print the result
    cout << cnt;
}
  
// Function that counts the minimum
// number of notes required with the
// given criteria
void solve(vector& A,
           vector >& P)
{
  
    Graph g(A.size());
  
    // Used to map the strings to
    // their respective indices
    unordered_map um;
    for (int i = 0; i < A.size(); i++) {
        um[A[i]] = i;
    }
  
    // Iterate through all the edges
    // and add them to the graph
    for (int i = 0; i < P.size(); i++) {
        int x = um[P[i][0]];
        int y = um[P[i][1]];
        g.addEdge(x, y);
    }
  
    // Function Call
    g.countSCCs();
}
  
// Driver Code
int main()
{
  
    vector arr
        = { "geeks", "for", "code",
            "run", "compile" };
    vector > P = { { "geeks", "for" },
                                  { "for", "code" },
                                  { "code", "run" },
                                  { "run", "compile" },
                                  { "run", "for" } };
  
    solve(arr, P);
  
    return 0;
}


输出:
3

时间复杂度: O(N + M)
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live