I am implementing an algorithm to determine whether an undirected graph is bipartite or not. Based on this pseudo-code made my implementation, which works for graphs connected, but when it is disconnected simply the program indicates a wrong answer. I think if its not connected, then one more loop is needed for every disjoint sub-graph. But im stuck with this. How I can solve my code for me to print a correct answer?
#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;
}
For example for this input
6 4
3 0
1 0
2 5
5 4
the output should be:
Is bipartite
0 1
1 2
2 1
3 2
4 1
5 2
Instead throws me the output:
0 1
1 2
2 0
3 2
4 0
5 0
This happens because the graph is not a connected graph, ie, has two connected components.I hope you can help me because I've been stuck with this for several days.
You should run bfs on every connected component. Simplest way to do this is to iterate over all vertices and if they weren't visited, then just call bfs on them.
bool is_bipartite()
{
for(int i = 0; i < numberVertex; i++)
{
if (visited[i] == 0 && !bfs(i)) {
return false;
}
}
return true;
}
It is still linear because, you run bfs on every connected component once.
#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;
}
The detailed implementation is as follows (C++ version). It will be able to handle several separated connected components.
Assume the graph node is defined as:
struct NODE
{
int color;
vector<int> neigh_list;
};
Then you can check whether the whole graph is bipartite by calling bfs().
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;
}
Bipartite graph is also known as 2-colour graph i.e we can colour all the nodes of the bipartite graph with only 2 colour such that no 2 adjacent node have same colour.
Initially let all vertex are not having any colour.
Start with any vertex and colour it with RED. Then Colour its all adjacent vertices with a colour other than RED let say Black.
Keep on repeating this
till all node are coloured. If at any point you found two adjacent
node have same colour. Then it is not a bipartite graph.
C++ Implementation
Related
I'm working on a algorithm problem, and it discribed as follows:
Suppose the deep learning model is a directed acyclic graph. If operator A depends on the output of operator B, then A can be calculated after the execution of B. If there is no dependency relation, then A can be executed in parallel. Given N nodes, the information of each node contains the execution time of the node and the list of the next nodes, and the shortest execution time of the neural network is calculated. The node index starts at 0.
and here is the input example:
7
A 10 1 2 3
B 9 4 5 6
C 22
D 20
E 19
F 18
G 21
Here is my solution:
#include <bits/stdc++.h>
using namespace std;
int dfs(int nodeTime, const vector<int>& nextNodes, vector<vector<int>> NN){
// Check whether the children of the current node have children
bool is_end = true;
for (int node : nextNodes) {
if (NN[node][1] != 0){
is_end = false;
break;
}
}
//The children of the current node have no children, find the maxTime
if (is_end) {
int maxTime = 0;
for (int node : nextNodes) {
maxTime = max(node, maxTime);
}
return nodeTime + maxTime;
}
//some children of the current node have children, keep doing dfs()
else{
int maxTime = 0;
for (int nodeIdx : nextNodes) {
if (NN[nodeIdx].size() != 1){
vector<int> next;
next.assign(NN[nodeIdx].begin() + 1, NN[nodeIdx].end());
maxTime = max(maxTime, dfs(NN[nodeIdx][0], next, NN));
}
else maxTime = max(maxTime, NN[nodeIdx][0]);
}
return maxTime + nodeTime;
}
}
int str_int(const string& s){
char c[10];
strcpy(c, s.c_str());
return atoi(c);
}
int main() {
// input stage
int n;
cin >> n;
vector<vector<int>> NN;
vector<int> temp;
vector<string> stemp;
string s;
for (int i = 0; i < n; ++i) {
stemp.clear();
temp.clear();
while (cin >> s){
stemp.push_back(s);
if (getchar() == '\n') break;
}
for (int j = 1; j < stemp.size(); ++j) {
temp.push_back(str_int(stemp[j]));
}
NN.push_back(temp);
}
vector<int> initialNextNodes; //Initialize the sequence of children of the starting node
initialNextNodes.assign(NN[0].begin() + 1, NN[0].end());
int res = dfs(NN[0][0], initialNextNodes, NN);
cout << res;
return 0;
}
The right output is 40, Debug mode gives the right answer, but Run mode gives the wrong answer, I can't figure out what went wrong. I looked up the common causes of this error, probably a pointer being used without space allocated, or a variable being used without an initial value assigned. But these do not seem to be the answer to my question, can anyone help me? I would be so grateful.
I am implementing bfs (Breadth First Search ) for the graph , but I am getting an error while I pass the starting value of the vector to an integer, for the dfs function to perform, as in the dfs function I have passed the source of the vector, i.e the first element of the vector.
error is on the line where start is declared to v[i]
Here is the complete code
#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;
vector<int> v[10];
bool visited[10];
int level[10];
int a = 0;
int arr[10];
void dfs(int s) //function should run only one time
{
queue<int> q;
q.push(s);
visited[s] = true;
level[s] = 0;
while (!q.empty())
{
int p = q.front();
arr[a] = p;
a++;
q.pop();
for (int i = 0; i < v[p].size(); i++)
{
if (visited[v[p][i]] == false) {
level[v[p][i]] = level[p] + 1;
q.push(v[p][i]);
visited[v[p][i]] = true;
}
}
}
}
int main()
{
char c;
int start; // starting element of the vector
int i = 0; // for keeping track of the parent
int countt = 0; // keep track of the no of parents
bool check;
printf("Child or Parent ?");
scanf("%c", &c);
while (countt <= 10) {
if (c == 'c') {
check = true;
int j = 0;
while (check) {
// to keep the track of the child;
scanf("%d", &v[i][j]);
j++;
}
}
if (c == 'p')
{
scanf("%d", &v[i]);
if (i == 0)
{
start = v[i];
}
i++;
countt++;
}
}
printf(" Vector input completed");
dfs(start);
printf("DFS completed, printing the dfs now ");
for (int g = 0; g <= 10; g++)
{
printf("%d", &arr[g]);
}
}
In your current code, v is an array of size 10 containing vector's. However, start is an int, so there is nothing strange in getting an error when trying to assign one to another.
I believe that you wanted v to be either an array of ints or vector of ints. In such a case you just have to declare v properly: int v[10] or vector<int> v(10).
This is general syntax: if you want to declare a vector with known size then you have to put it in (), not in []. Note that you can also fill the vector with some initial values (say zeroes) by writing vector<int> v(10, 0).
In case got you wrong and you wanted to store a graph as vector of vectors, then you can write vector<vector<int>> v(10).
I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other
bool pair(const int array[])
{
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
}
Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?
edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.
I was not trying to compile the code, for the record.
It will do neither:
i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.
If you really cant sort the array (which would be so easy with std::sort) then you can do this:
const int NumCards = 9; // If this is a constant, this definition should occur somewhere.
bool hasPair(const int array[], const int arraySize) {
int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set
// the array elements to 0.
// Iterate over all of the cards in your hand.
for (int i = 0; i < arraySize; i++) {
int myCurrentCard = array[i]; // Get the current card number.
// Increment it in the array.
possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1;
// Or the equivalent to the above in a single line.
possibleCards[array[i]]++; // Increment the card so that you
// count how many of each card is in your hand.
}
for (int i = 0; i < NumCards; ++i) {
// If you want to check for a pair or above.
if (possibleCards[i] >= 2) { return true; }
// If you want to check for exactly a pair.
if (possibleCards[i] == 2) { return true; }
}
return false;
}
This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.
do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array
#include <iostream>
using namespace std;
int* CheckForPairs(int[], int, int&);
int main()
{
int array[ ]= {2, 5, 5, 7, 7};
int nPairsFound = 0;
int* ptrPairs = CheckForPairs(array, 5, nPairsFound);
for(int i(0); i < nPairsFound; i++)
{
cout << ptrPairs[i] << endl;
}
if(ptrPairs)
{
delete[] ptrPairs;
ptrPairs = NULL;
}
return 0;
}
int* CheckForPairs(int array[] , int size, int& nPairsFound)
{
int *temp = NULL;
nPairsFound = 0;
int j = 0;
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
nPairsFound++;
}
temp = new int[nPairsFound];
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
{
temp[j] = i;
j++;
}
}
return temp;
}
You could use a std::unordered_set for a O(n) solution:
#include <unordered_set>
using namespace std;
bool hasMatchingElements(const int array[], int arraySize) {
unordered_set<int> seen;
for (int i = 0; i < arraySize; i++) {
int t = array[i];
if (seen.count(t)) {
return true;
} else {
seen.insert(t);
}
}
return false;
}
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.
You need a nested for loop:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int unsortedArray[] = {2,3,2,4,5};
int size = 5;
for(int i=0;i<size-1;i++)
{ for(int j=i+1;j<size;j++)
{ if(unsortedArray[i]==unsortedArray[j])
{ printf("matching cards found\n");
return 0;
}
}
}
printf("matching cards not found\n");
return 0;
}
----EDIT------
Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:
#include <iostream>
#include <stdio.h>
#include <stdbool.h>
#defin NUM_CARDS 52;
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int N,i,j;
cin>>N;
int unsortedArray[N];
for(int i=0;i<N;i++)
cin>>unsortedArray[i];
int count[NUM_CARDS]={0};
int cnt = 0;
for( i=0;i<N-1;i++)
{
for( j=i+1;j<N;j++)
{ if(unsortedArray[i]==-1)
break;
if(unsortedArray[i]==unsortedArray[j])
{
unsortedArray[j]=-1;
cnt++;
}
}
if(unsortedArray[i]!=-1)
{
count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
// determine the poker hand.
if(cnt==1)
cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else if(cnt>=2)
cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else
cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;
cnt = 0;
}
}
I have been trying to do a graph search for a problem from Hackerrank. Lastly, I have come up with
#include <cstdio>
#include <list>
using namespace std;
void bfs(list<int> adjacencyList[], int start, int countVertices) {
// initialize distance[]
int distance[countVertices];
for(int i=0;i < countVertices; i++) {
distance[i] = -1;
}
list<int>::iterator itr;
int lev = 0;
distance[start-1] = lev; // distance for the start vertex is 0
// using start -1 since distance is array which are 0-indexed
list<int> VertexQueue;
VertexQueue.push_back(start);
while(!VertexQueue.empty()) {
int neighbour = VertexQueue.front();
itr = adjacencyList[neighbour].begin();
while(itr != adjacencyList[neighbour].end()) {
int vertexInd = (*itr) - 1;
if(distance[vertexInd] == -1) { // a distance of -1 implies that the vertex is unexplored
distance[vertexInd] = (lev + 1) * 6;
VertexQueue.push_back(*itr);
}
itr++;
}
VertexQueue.pop_front();
lev++;
}
// print the result
for(int k=0;k< countVertices;k++) {
if (k==start-1) continue; // skip the start node
printf("%d ",distance[k]);
}
}
int main() {
int countVertices,countEdges,start,T,v1,v2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
// input edges in graph
for(int j=0; j<countEdges; j++) {
scanf("%d%d",&v1,&v2);
adjacencyList[v1].push_back(v2);
adjacencyList[v2].push_back(v1); // since the graph is undirected
}
scanf("%d",&start);
bfs(adjacencyList, start, countVertices);
printf("\n");
}
return 0;
}
However, this is resulting in 'Segmentation Fault' and I cannot figure out where I am going wrong.
Also, I have comes across segmentation fault a lot of times, but have no idea how to debug it. Would be great if someone can give me an idea of that.
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
Above code appears wrong. If your indices start with 1, either make adjacencyList of size countVertices + 1 or decrease u and v before putting them in the list.
You can also use a (an unordered) map mapping vertex to a list which will not segfault.
Also not that VLA are not part of standard C++, so avoid them even if your compiler support them as extension.
I need to create random conected undirected graph with even vertex degrees. I have to do that to test the times of finding Euler cycles for different vertex number (N). The representation of the graph is adjacency list. I have such code:
void make_graph()
{
int i,a,b,c;
int nasycenie;
nasycenie=(0.5)*((N*(N-1))/2);
if(nasycenie<N-1) nasycenie=N-1;
for(i=1;i<=nasycenie;++i)
{
if(i<N)
{
a=rand()%i;
b=i;
}
else
{
a=rand()%N;
b=rand()%(N-1);
b+=(b>=a);
}
L1[a].push_back(b);
L1[b].push_back(a);
}
}
It makes connected undirected graph but vertex degrees aren't even. How to improve that to have even vertex degrees?
This code will create the graph you specified , but in AdjacencyMatrix (only half a matrix actulay, since graph is undirect) presentation , it wouldn't be hard to turn it into an AdjacencyList.
bool[vNum][vNum] make_graph(int vNum)
{
bool[vNum][vNum] adjacency;
int edgeNum = rand()%C(vNum , 2);
for(int i=0 ; i<vNum; i++)
{
int j=0;
for(j ; j<i; j++)
{
adjacency[i][j] = rand()%2;
}
if(hasOddTrue(adjacency[i] , j))
{
int selectedIndex = rand()%j;
adjacency[i][selectedIndex ] = !adjacency[i][selectedIndex ];
}
}
return adjacency;
}
bool hasOddTrue(bool[] list , int length)
{
bool b = false;
for(int i=0 ; i<length ; i++) { b = xor(b, list[i]); }
return b;
}