class Graph
{
public:
Graph(int v);
int V()const;
int E()const;
void addEdge(int v, int w);
vector<int> adj(int v)const;
string toString()const;
}
int degree(Graph G. int v)
{
int cnt = 0;
for (int w : G.adj(v)) ++cnt;
return cnt;
}
int maxDegree(Graph G)
{
int maxCnt = 0;
for (int i = 0; i < G.V(); ++i)
if (degree(G, i) > maxCnt) maxCnt = degree(G, i);
return maxDegree;
}
int aveDegree(Graph G)
{
return G.E() * 2 / G.V();
}
int numberOfSelfLoops(Graph G)
{
int cnt = 0;
for (int v = 0; v < G.V(); ++i)
for (int w : G.adj(v))
if (w == v) ++cnt;
return cnt;
}
string toString (Graph G)
{
string s = G.V() + " vertices, " + G.E() + " edges\n";
for (int v = 0; v < G.V(); ++v)
{
s += v + ": ";
for (int w : G.adj(v))
s += w + " ";
s += "\n";
}
return s;
}
class Search : public Graph
{
Search(Graph G, int s);
bool marked(int v);
int count();
}
void dfs(Graph G, int v)
{
marked[v] = true;
++count;
for (int w : G.adj(v))
{
if (!marked[w]) dfs(G, w);
}
}
void bfs(Graph G, int v)
{
queue<int>que;
que.push(v);
while(!que.empty())
{
int t = que.pop();
marked[t] = true;
++count;
for (int w : G.adj(t))
{
if (!marked[w]) que.push(w);
}
}
}
class DFPaths
{
private:
bool* marked;
int* edgeTo;
int s;
void dfs(Graph G, int v)
{
marked[v] = true;
for (int w : G.adj(v))
{
if (!marked[w])
{
edge[w] = v;
dfs(G, w);
}
}
}
public:
DFPaths(Graph G, int s)
{
marked = new bool[G.V()];
edgeTo = new int[G.V()];
this.s = s;
dfs(G, s);
}
bool hasPathTo(int v)const { return marked[v]; }
vector<int> pathTo(int v)
{
vector<int>path;
if (!marked[v]) return path;
for (int x = v; x != s; x = edgeTo[x])
{
path.push_back(x);
}
path.push_back(s);
return path;
}
}
class CC
{
private:
bool* marked;
int* id;
int count;
void dfs(Graph G, int v)
{
marked[v] = true;
id[v] = count;
for (int w : G.adj(v))
{
if (!marked[w]) dfs(G, w);
}
}
public:
CC()
{
for (int i = 0; i < G.V(); ++i)
{
if (!marked[i])
{
dfs(G, i);
++count;
}
}
}
bool connected(int v, int w)const { return id[v] == id[w]; }
int id(int v)const { return id[v]; }
int count()const { return count; }
}
class Cycle
{
private:
bool* marked;
bool hasCycle;
void dfs(Graph G, int v, int u)
{
marked[v] = true;
for (int w : G.adj(v))
{
if (!marked[w]) dfs(G, w, v);
else if (w != u) hasCycle = true;
}
}
public:
Cycle(Graph G)
{
marked = new bool[G.V()];
for (int s = 0; s < G.V(); ++s)
if (!marked[s]) dfs(G, s, s);
}
bool hasCycle()const { return hasCycle; }
}
class TwoColor
{
private:
bool* marked;
bool* color;
bool isTwoColorable;
void dfs(Graph G, int v)
{
marked[v] = true;
for (int w : G.adj(v))
{
if (!marked[v])
{
color[w] = !color[v];
dfs(G, w);
}
else
{
if (color[v] == color[w])
isTwoColorable = false;
}
}
}
public:
TwoColor(Graph G)
{
marked = new bool[G.V()];
color = new bool[G.V()];
for (int s = 0; s < G.V(); ++s)
{
if (!marked[s]) dfs(G, s);
}
}
bool isBipartite()const { return isTwoColorable; }
}