Как проверить, является ли граф двухцветным или нет?

Я хочу найти, является ли граф 2-раскрашиваемым или не более, т.е. двудольный или не двудольный.

Вот мой код на С++. Я использую валлийский алгоритм Пауэлла, но что-то не так в коде, может быть, я пропускаю некоторые угловые случаи или какую-то логическую ошибку.

Введите n=нет. вершины, m = нет. ребер, индексация на основе 0

#include <iostream>
#include <algorithm>
using namespace std;


 pair <int,int> s[1001];
 int comp( pair <int,int> s1, pair <int,int> s2)
 {
     if(s1.first>s2.first)
        return 0;
     else
        return 1;
 }
int main()
{

        int n,i,j,k,flag=0;
        bool a[1001][1001]={false};
        int s1[1001]={0};
        int s3[1001]={0};
        for(i=0;i<1001;i++)
        {
            s[i].first=0;
            s[i].second=i;
            //s1[i]=0;
        }
        long long m;
        cin>>n>>m;
        while(m--)
        {
            int x,y;
            cin>>x>>y;
            if(x==y)
                continue;
            a[x][y]=true;
            a[y][x]=true;
        }

        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
            if(a[i][j]==true )
            s[i].first++;

        sort(s,s+n,comp);
        int color=1,p=0,z,f;

        for(i=0;i<n;i++)
        {
            k = s[n-i-1].second;
            if(s1[k]==0)
            {
                s1[k]=color;
                p=0;
                    s3[p++]=k;
                    for(j=n-1;j>=0;j--)
                    {
                        f=0;
                        if(s1[s[j].second]==0)
                        {
                            for(z=0;z<p;z++)
                            {
                                if(a[s3[z]][s[j].second]==false || s3[z]==s[j].second)
                                    continue;
                                else
                                {
                                    f=1;
                                    break;
                                }
                            }
                            if(f==1)
                                continue;
                            else
                            {
                                s3[z]=s[j].second;
                                p++;
                                s1[s[j].second]=color;
                            }
                        }
                    }

                color++;
            }
            if(color==3)
                break;
        }
        for(i=0;i<n;i++)
            if(s1[i]==0)
        {
            flag=1;
            break;
        }

            if(flag==1)
            cout<<"NO\n";
            else
            cout<<"YES\n";

    return 0;
}

person Udbhav Govil    schedule 08.09.2016    source источник
comment
Объясните, пожалуйста, откуда вы знаете, что это неправильно?   -  person Guenther    schedule 08.09.2016
comment
это из живого конкурса, поэтому я не могу обсуждать этот вопрос здесь.   -  person Udbhav Govil    schedule 08.09.2016
comment
Как вы ожидаете, что мы поможем вам, если вы не можете это обсудить?   -  person SurvivalMachine    schedule 08.09.2016
comment
я хочу, чтобы некоторые увидели, есть ли какая-либо логическая ошибка в моем коде, или есть ли случай, когда мой код может дать сбой, или какой-то специальный двухцветный график? Как только конкурс закончится, я опубликую исходный вопрос   -  person Udbhav Govil    schedule 08.09.2016


Ответы (3)


Чтобы показать, что граф является двудольным, вам не нужен сложный алгоритм для проверки. Вы можете просто использовать раскрашивающую функцию DFS (поиск в глубину). Это может быть реализовано следующим образом:

int color[100005];              //I assume this is the largest input size, initialise all values to -1.
vector<int> AdjList[100005];    //Store the neighbours of each vertex
bool flag = true;               //Bipartite or Not Bipartite

void dfs(int x, int p){         //Current vertex, Parent Vertex
    if (!flag) return;
    if (p == -1) color[x] = 0;
    else color[x] = 1 - color[p];
    for (int i = 0; i < AdjList[x].size(); ++i){      //For Every Neighbour
        int v = AdjList[x][i];                        //Vertex to be checked
        if (color[v] == color[x]){                    //Same color -> Not bipartite
            flag = false;
            return;
        }      
        if (color[v] == -1){                           //Unchecked
            dfs(v,x);                                  //color
        }              
    }
}
person Benson Lin    schedule 08.09.2016
comment
Вы уверены, что он охватывает все случаи? - person Udbhav Govil; 08.09.2016

Исходная проблема: https://www.codechef.com/problems/CHFNFRN

@Benson Lin Спасибо за такую ​​помощь.

Что ж, проблема с вашим ответом заключается в том, что он не работает, если граф отключен, то есть если он имеет 2 отключенных подграфа. Поскольку мы выбираем исходный узел случайным образом, приведенный выше код просто проверяет этот подграф с этим узлом и дает ответ только для подграфа, а не для графа. С небольшим изменением в приведенном выше коде мы можем решить эту проблему.

int colorArr[1001];

bool isBipartite(bool G[][1001], int src,int n)
{
colorArr[src] = 0;
queue <int> q;
q.push(src);
while (!q.empty())
{
    int u = q.front();
    q.pop();

     // Find all non-colored adjacent vertices
    for (int v = 0; v < n; ++v)
    {
        // An edge from u to v exists and destination v is not colored
        if (G[u][v]==true && colorArr[v] == -1)
        {
            // Assign alternate color to this adjacent v of u
            colorArr[v] = 1 - colorArr[u];
            q.push(v);
        }
         if(G[u][v]==true && colorArr[u]==colorArr[v] && u!=v)
                return false;

        //  An edge from u to v exists and destination v is colored with
        // same color as u
    }
}

// call the function with source node which is not color.
int count=0;
for(int i=0;i<n;i++)
{

        if(colorArr[i]==-1)
        {
            if(isBipartite(G,i,n))
            continue;
            else
                return false;
        }
    for(int j=0;j<n;j++)
    {
        if(G[i][j]==true )
        {
            if(colorArr[i]==colorArr[j] && colorArr[i]!=-1)
                return false;
        }

    }
}

return true;
 }
person Udbhav Govil    schedule 24.09.2016

BFS можно использовать, раскрашивая чередующиеся уровни разными цветами и останавливаясь, если два узла одного цвета находятся рядом (не двудольные) или не обнаруживается такая несовместимая окраска (двудольный). Вот код Python (adj — это список смежности для входного графа, который нужно проверить):

def bipartite(adj):
    color = [None]*len(adj)
    for vertex in range(len(adj)):
        if not color[vertex]:
            queue = [vertex]
            color[vertex] = 'red'
            while len(queue) > 0:
                u = queue.pop(0)
                for v in adj[u]:
                    if color[v] ==  color[u]:
                        return 0
                    if not color[v]:
                        queue.append(v)
                        color[v] = 'red' if color[u] == 'blue' else 'blue'
    return 1

Следующая анимация показывает результат запуска bfs на заданном входном графе и раскраску графа в 2 цвета (также показана очередь bfs).

введите здесь описание изображения

person Sandipan Dey    schedule 10.10.2020