📜  使用位掩码在图形中查找母顶点

📅  最后修改于: 2021-05-19 19:59:18             🧑  作者: Mango

图G =(V,E)中的母顶点是顶点v,因此从v开始的路径可以通过从v开始的路径到达G中的所有其他顶点。
例子:

方法:

我们可以使用“深度优先搜索”方法解决此问题。为了进一步优化我们的方法,我们将使用有效的解决方案。

下面的解决方案也使用“深度优先搜索”来解决此问题,但是它仅执行一次“深度优先搜索周期”,并且一旦找到母顶点,就会停止执行。

  • 在执行深度优先搜索时,我们有一个位掩码数组,代表每个顶点的位掩码。在执行期间,此位掩码数组将传递到所有顶点。
  • 每个顶点都以这样一种方式修改其专用位掩码:可以从该顶点访问包括顶点在内的所有设置位,包括当前顶点。
  • 在每次迭代中,我们通过检查当前顶点位掩码值(如果设置了代表所有顶点的位)来检查是否可以从该顶点访问所有顶点。如果可以从该顶点访问所有顶点,则它将中断执行,并找到母顶点作为当前顶点。
  • 如果已经从Vertex-1访问了Vertex-2,并且较早已经访问了Vertex-2,则Vertex-1通过对Vertex-2位掩码执行“或”操作来更新其位掩码。

时间复杂度: O(V + E)

上述想法如何运作?

让这种方法支持最多具有32个顶点的图。可以扩展此方法以支持更多数量的顶点,但是此处最多处理32个顶点。

  1. 创建了一个由32个位掩码组成的位掩码数组。数组的第0个索引表示Vertex-0的位掩码,而数组的第一个索引表示Vertex-1的位掩码,依此类推。
  2. 使用深度优先搜索算法访问图的所有顶点,并将相同的位掩码数组传递到所有顶点。相应地设置了位掩码值,以表示可以从该顶点访问的所有顶点。
  3. 设置与相邻顶点相对应的位索引,包括自己的位索引。相邻顶点的位掩码也将重复相同的操作,并将其返回给Vertex-1。
  4. 顶点1将继续对其位掩码的所有邻居的返回值执行“或”运算,以表示可以从顶点1访问的所有顶点。
  5. 请注意,如果Vertex-2是Vertex-1的邻居,并且已经从另一个邻居顶点访问过,那么它将不会再次访问其邻居的顶点,并将其位掩码返回到第一个节点。
  6. 每次迭代将检查是否将与当前顶点对应的位掩码的所有位都设置为1。如果将当前顶点均值的所有位都设置为1,则意味着可以从当前顶点访问所有顶点,并且当前顶点是的母顶点。该图。

以下是我们上述方法的实现:

// C++ code to find Mother
// Vertex using Bitmask
  
#include 
#include 
  
using namespace std;
  
struct Graph {
    int V;
  
    // Store in descending order
    set >* adjList;
};
  
Graph* CreateGraph(int N)
{
    Graph* g = new Graph();
    g->V = N;
    g->adjList
        = new set >[N];
    return g;
}
  
void AddEdge(
    Graph* g, int src, int dest)
{
  
    g->adjList[src].insert(dest);
}
  
void PrintGraph(Graph* g)
{
  
    set >::iterator it;
  
    for (int i = 0; i < g->V; i++) {
  
        for (it = g->adjList[i].begin();
             it != g->adjList[i].end();
             it++) {
            cout << "There is an edge from "
                 << i << " to "
                 << *it << endl;
        }
    }
}
  
bool IsEdge(Graph* g, int src, int dest)
{
    if (g->adjList[src].find(dest)
        != g->adjList[src].end()) {
  
        return true;
    }
    return false;
}
  
int MotherVertexUtil(
    Graph* g, int index,
    int* mask, int* m_vertex)
{
  
    // If mother vertex is already found
    // then simply return with existing
    // mask of the vertex index
    if (*m_vertex != -1) {
  
        return mask[index];
    }
  
    // if this vertex is already visited,
    // return the bit-mask
    // value of this vertex.
    if (mask[index] != 0) {
        return mask[index];
    }
  
    int tmpmask = 0;
  
    // Set the bit corresponding
    // to vertex index in tmpmask
    tmpmask |= (1 << index);
  
    for (int i = 0; i < g->V; i++) {
        if ((index != i)
            && IsEdge(g, index, i)) {
  
            // Set bits corresponding to all
            // vertex which can be visite
            // by this vertex by ORing
            // the return value by util function
  
            // Vertex is not visited
            if (mask[i] == 0) {
  
                int retmask
                    = MotherVertexUtil(
                        g, i, mask, m_vertex);
                tmpmask |= retmask;
            }
  
            // Vertex is already visited
            else {
                tmpmask |= mask[i];
            }
  
            // Check if current vertex is
            // mother vertex or mother vertex
            // is already found
            if (tmpmask == (pow(2, g->V) - 1)) {
  
                // If all bits of a mask is set
                // it means current vertex
                // is mother vertex
                if (*m_vertex == -1) {
                    *m_vertex = index;
                }
                return tmpmask;
            }
        }
    }
  
    // populate tmpmask as final
    // bit mask of the vertex
    mask[index] |= tmpmask;
  
    return mask[index];
}
  
int MotherVertex(Graph* g)
{
  
    int v = g->V;
    int* mask = new int(v);
  
    // Initially bit mask
    // for all vertex will be 0
    for (int i = 0; i < v; i++) {
        mask[i] = 0;
    }
  
    // DFS traversal is used to check
    // for the mother vertex
    // All set bits (of bitmask of a vertex)
    // represent the current vertex index
    // and index of vertices which could be
    // visited from the current vertex.
  
    /* Example:
       If a vertex index is 3
       then and vertex 5, 7 and 10
       can be visited from this vertex
       then final bit mask of this vertex
       would be
       00000000000000000000010010101000
       (bits 3, 5, 7 and 10 are set) */
  
    // tmpmask is used to store
    // the final bitmask of the vertex.
    int tmpmask = 0;
  
    // flag to check if
    // mother vertex is found
    int m_vertex = -1;
  
    for (int index = 0; index < v; index++) {
  
        // set the bit corresponding
        // to vertex index in tmpmask
        tmpmask = (1 << index);
  
        // mask for a vertex is 0
        // means it has not yet
        // visited so visit this vertex
        if (mask[index] == 0) {
  
            int retmask
                = MotherVertexUtil(
                    g, index,
                    mask, &m_vertex);
  
            // set bits corresponding to all
            // vertices which can be visited
            // from this vertex by ORing
            // the return value by util function
            tmpmask |= retmask;
        }
  
        // check if current vertex is
        // mother vertex or mother vertex
        // is already found
        // If all bits of a mask is set
        // it means current vertex
        // is mother vertex
        if (tmpmask == (pow(2, v) - 1)) {
  
            // current vertex is mother vertex
            if (m_vertex == -1) {
                m_vertex = index;
            }
            break;
        }
  
        // populate tmpmask as final bit
        // mask of the vertex
        mask[index] |= tmpmask;
    }
  
    return m_vertex;
}
  
// Driver code
int main()
{
  
    Graph* g = CreateGraph(7);
    AddEdge(g, 0, 2);
    AddEdge(g, 0, 1);
    AddEdge(g, 1, 3);
    AddEdge(g, 4, 1);
    AddEdge(g, 5, 2);
    AddEdge(g, 5, 6);
    AddEdge(g, 6, 0);
    AddEdge(g, 6, 4);
    PrintGraph(g);
  
    int m_vertex = MotherVertex(g);
    if (m_vertex == -1) {
  
        cout << "Mother vertex is not"
             << " existing in this graph"
             << endl;
    }
    else {
        cout << "Mother vertex is: "
             << m_vertex << endl;
    }
    return 0;
}
输出:
There is an edge from 0 to 2
There is an edge from 0 to 1
There is an edge from 1 to 3
There is an edge from 4 to 1
There is an edge from 5 to 6
There is an edge from 5 to 2
There is an edge from 6 to 4
There is an edge from 6 to 0
Mother vertex is: 5

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。