【问题标题】:BFS to check if a graph is bipartite in c++BFS检查图是否在c ++中是二分的
【发布时间】:2012-03-27 04:32:40
【问题描述】:

我正在实现一种算法来确定无向图是否是二分图。基于this pseudo-code 进行了我的实现,它适用于连接的图形,但是当它断开连接时,程序会指示错误的答案。我认为如果它没有连接,那么每个不相交的子图都需要一个循环。但我坚持这一点。如何解决我的代码以打印正确答案?

#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;

#define MAX 1000

int numberVertex, numberEdges;
int particion[MAX], visited[MAX];
vector< int > adjacencyMatrix[MAX];

bool bfs()
{
    int i, origin, destination, begin;
    queue< int > queueVertex;
    begin = 0;
    queueVertex.push(begin);
    particion[begin] = 1; // 1 left,
    visited[begin] = 1; // set adjacencyMatrixray

    while(!queueVertex.empty())
    {
        origin = queueVertex.front(); queueVertex.pop();
        for(i=0; i < adjacencyMatrix[origin].size(); i++)
        {
            destination = adjacencyMatrix[origin][i];
            if(particion[origin] == particion[destination])
            {
                return false;
            }
            if(visited[destination] == 0)
            {
                visited[destination] = 1;
                particion[destination] = 3 - particion[origin]; // alter 1 and 2 subsets
                queueVertex.push(destination);
            }
        }
    }
    return true;
}

int main()
{
 freopen("tarea2.in", "r", stdin);
    int i,j, nodeOrigin, nodeDestination;
    scanf("%d %d", &numberVertex, &numberEdges);
    for(i=0; i<numberEdges; i++)
    {
        scanf("%d %d", &nodeOrigin, &nodeDestination);
        adjacencyMatrix[nodeOrigin].push_back(nodeDestination);
        adjacencyMatrix[nodeDestination].push_back(nodeOrigin);
    }
    if(bfs()) {

        printf("Is bipartite\n");
          for (j=0; j<numberVertex; j++){
        cout<<j<<" "<<particion[j]<<endl;
        }

    }
    else {printf("Is not bipartite\n");}





    return 0;
}

例如对于这个输入

6 4
3 0
1 0
2 5
5 4

输出应该是:

Is bipartite
0 1
1 2
2 1
3 2
4 1
5 2

而是向我抛出输出:

0 1
1 2
2 0
3 2
4 0
5 0

发生这种情况是因为该图不是连通图,即具有两个连通分量。我希望您能帮助我,因为我已经被这个问题困扰了好几天了。

【问题讨论】:

    标签: c++ graph-theory breadth-first-search bipartite


    【解决方案1】:

    您应该在每个连接的组件上运行 bfs。执行此操作的最简单方法是遍历所有顶点,如果没有访问过它们,则只需对它们调用 bfs。

    bool is_bipartite()
    {
        for(int i = 0; i < numberVertex; i++)
        {
           if (visited[i] == 0 && !bfs(i)) {
               return false;
           }
        } 
        return true;
    }
    

    它仍然是线性的,因为你在每个连接的组件上运行一次 bfs。

    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <iostream>
    using namespace std;
    
    #define MAX 1000
    
    int numberVertex, numberEdges;
    int particion[MAX], visited[MAX];
    vector< int > adjacencyMatrix[MAX];
    
    bool bfs(int begin)
    {
        int i, origin, destination;
        queue< int > queueVertex;
        queueVertex.push(begin);
        particion[begin] = 1; // 1 left,
        visited[begin] = 1; // set adjacencyMatrixray
    
        while(!queueVertex.empty())
        {
            origin = queueVertex.front(); queueVertex.pop();
            for(i=0; i < adjacencyMatrix[origin].size(); i++)
            {
                destination = adjacencyMatrix[origin][i];
                if(particion[origin] == particion[destination])
                {
                    return false;
                }
                if(visited[destination] == 0)
                {
                    visited[destination] = 1;
                    particion[destination] = 3 - particion[origin]; // alter 1 and 2 subsets
                    queueVertex.push(destination);
                }
            }
        }
        return true;
    }
    
    bool is_bipartite()
    {
        for(int i=0; i< numberVertex; i++)
        {
           if (visited[i] == 0 && !bfs(i)) {
               return false;
           }
        } 
        return true;
    }
    
    int main()
    {
        //freopen("tarea2.in", "r", stdin);
        int i,j, nodeOrigin, nodeDestination;
        scanf("%d %d", &numberVertex, &numberEdges);
        for(i=0; i<numberEdges; i++)
        {
            scanf("%d %d", &nodeOrigin, &nodeDestination);
            adjacencyMatrix[nodeOrigin].push_back(nodeDestination);
            adjacencyMatrix[nodeDestination].push_back(nodeOrigin);
        }
        if(is_bipartite()) {
    
            printf("Is bipartite\n");
              for (j=0; j<numberVertex; j++){
            cout<<j<<" "<<particion[j]<<endl;
            }
    
        }
        else {printf("Is not bipartite\n");}
    
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      具体实现如下(C++版本)。它将能够处理几个分离的连接组件。

      假设图节点定义为:

      struct NODE
      {
          int color;
          vector<int> neigh_list;
      };
      

      然后你可以通过调用bfs()来检查整个图是否为bipartite

      bool checkAllNodesVisited(NODE *graph, int numNodes, int & index);
      
      bool bfs(NODE * graph, int numNodes)
      {
          int start = 0;
      
          do 
          {
              queue<int> Myqueue;
              Myqueue.push(start);
              graph[start].color = 0;
      
              while(!Myqueue.empty())
              {
                  int gid = Myqueue.front();
                  for(int i=0; i<graph[gid].neigh_list.size(); i++)
                  {
                      int neighid = graph[gid].neigh_list[i];
                      if(graph[neighid].color == -1)
                      {
                          graph[neighid].color = (graph[gid].color+1)%2; // assign to another group
                          Myqueue.push(neighid);
                      }
                      else
                      {
                          if(graph[neighid].color == graph[gid].color) // touble pair in the same group
                              return false;
                      }
                  }
                  Myqueue.pop();
              }
          } while (!checkAllNodesVisited(graph, numNodes, start)); // make sure all nodes visited 
                                                  // to be able to handle several separated graphs, IMPORTANT!!!
      
          return true;
      }
      
      bool checkAllNodesVisited(NODE *graph, int numNodes, int & index)
      {
          for (int i=0; i<numNodes; i++)
          {
              if (graph[i].color == -1)
              {
                  index = i;
                  return false;
              }
          }
      
          return true;
      }
      

      【讨论】:

        【解决方案3】:

        二分图也称为 2 色图,即我们可以只用 2 种颜色为二分图的所有节点着色,使得没有 2 个相邻节点具有相同的颜色。

        • 最初让所有顶点没有任何颜色。

        • 从任意顶点开始并用红色着色。然后用红色以外的颜色为其所有相邻顶点着色,比如说黑色。

        • 继续重复这个 直到所有节点都着色。如果在任何时候你发现两个相邻的 节点具有相同的颜色。那么它就不是二分图了。

        C++ Implementation

        【讨论】:

        • 你应该通过添加一些源代码来增强你的答案
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 2021-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-01
        • 2022-11-23
        相关资源
        最近更新 更多