refer to
http://algs4.cs.princeton.edu/41undirected/
#include <iostream>
#include <vector>#include <stack>
#include <queue>
#include <string.h>
using std::vector;
using std::stack;
using std::queue;
using std::cout;
using std::endl;
class Graph
{
public:
Graph(int vCnt, int eCnt, int arr[][2])
{
numVertice = vCnt;
numEdge = eCnt;
adj = new vector<int>[vCnt];
for (int i = 0; i < vCnt; ++i)
adj[i].clear();
for (int t = 0; t < eCnt; ++t)
{
adj[arr[t][0]].push_back(arr[t][1]);
adj[arr[t][1]].push_back(arr[t][0]);
}
}
~Graph()
{
delete []adj;
adj = NULL;
}
vector<int> getAdj(int v)
{
return adj[v];
}
int getVerticeNum()
{
return numVertice;
}
int getEdgeNum()
{
return numEdge;
}
void show()
{
for (int i = 0; i < numVertice; ++i)
{
cout << i << ": ";
int size = adj[i].size();
for (int j = 0; j < size; ++j)
cout << adj[i][j] << " ";
cout << endl;
}
}
private:
int numVertice;
int numEdge;
vector<int> *adj;
};
class DepthFirstSearch
{
public:
DepthFirstSearch(Graph *g, int s, bool recursive)
{
count = 0;
marked = new bool[g->getVerticeNum()];
memset(marked, false, sizeof(bool)*(g->getVerticeNum()));
if (recursive)
recursivedfs(g, s);
else
dfs(g, s);
}
~DepthFirstSearch()
{
delete []marked;
marked = NULL;
}
int getCnt()
{
return count;
}
private:
void recursivedfs(Graph *g, int s)
{
++count;
marked[s] = true;
int size = g->getAdj(s).size();
for (int i = 0; i < size; ++i)
if (!marked[g->getAdj(s)[i]])
recursivedfs(g, g->getAdj(s)[i]);
}
void dfs(Graph *g, int s)
{
++count;
marked[s] = true;
stack<int> st;
st.push(s);
while (!st.empty())
{
int cur = st.top();
int i, size = g->getAdj(cur).size();
for (i = 0; i < size; ++i)
if (!marked[g->getAdj(cur)[i]])
{
++count;
marked[g->getAdj(cur)[i]] = true;
st.push(g->getAdj(cur)[i]);
break;
}
if (i >= size)
st.pop();
}
}
private:
int count;
bool *marked;
};
class BreadthFirstSearch
{
public:
BreadthFirstSearch(Graph *g, int s)
{
count = 0;
marked = new bool[g->getVerticeNum()];
memset(marked, false, sizeof(bool)*(g->getVerticeNum()));
bfs(g, s);
}
~BreadthFirstSearch()
{
delete []marked;
marked = NULL;
}
int getCnt()
{
return count;
}
private:
void bfs(Graph *g, int s)
{
++count;
marked[s] = true;
queue<int> qu;
qu.push(s);
while (!qu.empty())
{
int cur = qu.front();
int i, size = g->getAdj(cur).size();
for (i = 0; i < size; ++i)
if (!marked[g->getAdj(cur)[i]])
{
++count;
marked[g->getAdj(cur)[i]] = true;
qu.push(g->getAdj(cur)[i]);
}
qu.pop();
}
}
private:
int count;
bool *marked;
};
class Cycle
{
public:
Cycle(Graph *g)
{
int size = g->getVerticeNum();
marked = new bool[size];
memset(marked, false, size);
if (hasSelfLoop(g))
return ;
if (hasParallelEdges(g))
return ;
edgeTo = new int[size];
memset(edgeTo, -1, sizeof(int)*size);
for (int v = 0; v < size; ++v)
if (!marked[v])
dfs(g, -1, v);
}
~Cycle()
{
if (NULL != marked)
{
delete []marked;
marked = NULL;
}
if (NULL != edgeTo)
{
delete []edgeTo;
edgeTo = NULL;
}
}
bool hasCycle()
{
return cycle.size() > 0 ? true : false;
}
void showCycle()
{
while (!cycle.empty())
{
cout << cycle.top() << " <- ";
cycle.pop();
}
}
private:
bool hasSelfLoop(Graph *g)
{
int size = g->getVerticeNum();
for (int v = 0; v < size; ++v)
{
int len = g->getAdj(v).size();
for (int i = 0; i < len; ++i)
if (v == g->getAdj(v)[i])
{
cycle.push(v);
cycle.push(v);
return true;
}
}
return false;
}
bool hasParallelEdges(Graph *g)
{
int size = g->getVerticeNum();
for (int v = 0; v < size; ++v)
{
// check for parallel edges incident to v
int len = g->getAdj(v).size();
for (int i = 0; i < len; ++i)
{
if (marked[g->getAdj(v)[i]])
{
cycle.push(v);
cycle.push(g->getAdj(v)[i]);
cycle.push(v);
return true;
}
marked[g->getAdj(v)[i]] = true;
}
// reset so marked[v] = false for all v
for (int j = 0; j < len; ++j)
marked[g->getAdj(v)[j]] = false;
}
return false;
}
void dfs(Graph *g, int u, int v)
{
marked[v] = true;
int size = g->getAdj(v).size();
for (int i = 0; i < size; ++i)
{
if (cycle.size() > 0)
return ;
if (!marked[g->getAdj(v)[i]])
{
edgeTo[g->getAdj(v)[i]] = v;
dfs(g, v, g->getAdj(v)[i]);
}
else if (g->getAdj(v)[i] != u)
{
for (int x = v; x != g->getAdj(v)[i]; x = edgeTo[x])
cycle.push(x);
cycle.push(g->getAdj(v)[i]);
cycle.push(v);
}
}
}
private:
bool *marked;
int *edgeTo;
stack<int> cycle;
};
int main()
{
int vNum = 13;
int eNum = 13;
int arr[][2] = {
{0, 5}, {4, 3}, {0, 1}, {9, 12},
{6, 4}, {5, 4}, {0, 2}, {11, 12},
{9, 10}, {0, 6}, {7, 8}, {9, 11},
{5, 3}
};
Graph graph(vNum, eNum, arr);
graph.show();
DepthFirstSearch dfs(&graph, 0, false);
if (graph.getVerticeNum() != dfs.getCnt())
{
cout << "total num: " << graph.getVerticeNum() << endl;
cout << "dfs from 0 can visit " << dfs.getCnt() << " vertices" << endl;
cout << "disconnected" << endl;
}
else
cout << "connected" << endl;
BreadthFirstSearch bfs(&graph, 0);
if (graph.getVerticeNum() != dfs.getCnt())
{
cout << "total num: " << graph.getVerticeNum() << endl;
cout << "bfs from 0 can visit " << bfs.getCnt() << " vertices" << endl;
cout << "disconnected" << endl;
}
else
cout << "connected" << endl;
Cycle finder(&graph);
if (finder.hasCycle())
{
cout << "show cycle" << endl;
finder.showCycle();
cout << endl;
}
else
cout << "graph is acycle" << endl;
return 0;
}