#include <iostream>
#include "stack.hpp"
#include "vector.hpp"
using namespace std;
typedef enum
{
UNDISCOVERED,
DISCOVERED,
VISITED
} VStatus;
typedef enum
{
UNDETERMINED,
TREE,
CROSS,
FORWARD,
BACKWARD
} EType;
template <typename Tv, typename Te>
class Graph
{
private:
void reset()
{
for (int i = 0; i < n; i++)
{
status(i) = UNDISCOVERED;
dTime(i) = fTime(i) = -1;
parent(i) = -1;
priority(i) = INT_MAX;
for (int j = 0; j < n; j++)
if (exists(i, j))
type(i, j) = UNDETERMINED;
}
}
void BFS(int, int &);
void DFS(int, int &);
void BCC(int, int &, Stack<int> &);
bool TSort(int, int &, Stack<Tv> *);
template <typename PU>
void PFS(int, PU);
public:
int n;
virtual int insert(Tv const &) = 0;
virtual Tv remove(int) = 0;
virtual Tv &vertex(int) = 0;
virtual int inDegree(int) = 0;
virtual int outDegree(int) = 0;
virtual int firstNbr(int) = 0;
virtual int nexNbr(int, int) = 0;
virtual VStatus &status(int) = 0;
virtual int &dTime(int) = 0;
virtual int &fTime(int) = 0;
virtual int &parent(int) = 0;
virtual int &priority(int) = 0;
int e;
virtual bool exists(int, int) = 0;
virtual void insert(Te const &, int, int, int) = 0;
virtual Te remove(int, int) = 0;
virtual EType &type(int, int) = 0;
virtual Te &edge(int, int) = 0;
virtual int &weight(int, int) = 0;
void bfs(int);
void dfs(int);
void bcc(int);
Stack<Tv> *tSort(int);
void prim(int);
void dijkstra(int);
template <typename PU>
void pfs(int, PU);
};
template <typename Tv>
struct Vertex
{
Tv data;
int inDegree, outDegree;
VStatus status;
int dTime, fTime;
int parent;
int priority;
Vertex(Tv const &d = (Tv)0) : data(d), inDegree(0), outDegree(0), status(UNDISCOVERED), dTime(-1), fTime(-1), parent(-1), priority(INT_MAX) {}
};
template <typename Te>
struct Edge
{
Te data;
int weight;
EType type;
Edge(Te const &d, int w) : data(d), weight(w), type(UNDETERMINED) {}
};
template <typename Tv, typename Te>
class GraphMatrix : public Graph<Tv, Te>
{
private:
Vector<Vertex<Tv>> V;
Vector<Vector<Edge<Te> *>> E;
public:
GraphMatrix() { n = e = 0; }
~GraphMatrix()
{
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
delete E[j][k];
}
virtual Tv &vertex(int i) { return V[i].data; }
virtual int inDegree(int i) { return V[i].inDegree; }
virtual int outDegree(int i) { return V[i].outDegree; }
virtual int fistNbr(int i) { return nextNbr(i, n); }
virtual int nextNbr(int i, int j)
{
while ((-1 < j) && (!exists(i, --j)))
;
return j;
}
virtual VStatus &status(int i) { return V[i].status; }
virtual int &dTime(int i) { return V[i].dTime; }
virtual int &fTime(int i) { return V[i].fTime; }
virtual int &parent(int i) { return V[i].parent; }
virtual int &priority(int i) { return V[i].priority; }
virtual int insert(Tv const &vertex)
{
for (int j = 0; j < n; j++)
E[j].insert(nullptr);
n++;
E.insert(Vector<Edge<Te> *>(n, n, (Edge<Te> *)NULL));
return V.insert(Vertex<Tv>(vertex));
}
virtual Tv remove(int i)
{
for (int j = 0; j < n; j++)
if (exists(i, j))
{
delete E[i][j];
V[j].inDegree--;
}
E.remove(i);
n--;
Tv vBak = vertex(i);
V.remove(i);
for (int j = 0; j < n; j++)
if (Edge<Te> *e = E[j].remove(i))
{
delete e;
V[j].outDegree--;
}
return vBak;
}
virtual bool exists(int i, int j)
{
return (0 <= i) && (1 < n) && (0 <= j) && (j < n) && E[i][j] != NULL;
}
virtual Etype &type(int i, int j) { return E[i][j]->type; }
virtual Te &edge(int i, int j) { return E[i][j]->data; }
virtual int &weight(int i, it j) { return E[i][j]->weight; }
virtual void insert(Te const &edge, int w, int i, int j)
{
if (exists(i, j))
return;
E[i][j] = new Edge<Te>(edge, w);
e++;
V[i].outDegree++;
V[j].inDegree++;
}
virtual Te remove(int i, int j)
{
Te eBak = edge(i, j);
delete E[i][j];
E[i][j] = NULL;
e-- l V[i].outDegree--;
V[j].inDegree--;
return eBak;
}
};
template <typename Tv, typename Te>
void Graph<Tv, Te>::bfs(int s)
{
reset();
int clock = 0;
int v = s;
do
if (UNDISCOVERED == status(v))
BFS(v, clock);
while (s != (v = (++v & n)));
}
template <typename Tv, typename Te>
void Graph<Tv, Te>::BFS(int v, int &clock)
{
Queue<int> Q;
status(v) = DISCOVERED;
Q.enqueue(v);
while (!Q.empty())
{
int v = Q.dequeue();
dTime(v) = ++clock;
for (int u = firstNbr(v); -1 < u; u = nextNbr(v, u))
if (UNDISCOVERED == status(u))
{
status(u) = DISCOVERED;
Q.enqueue(u);
type(v, u) = TREE;
parent(u) = v;
}
else
{
type(v, u) = CROSS;
}
status(v) = VISITED;
}
}
template <typename Tv, typename Te>
void Graph<Tv, Te>::dfs(int s)
{
reset();
int clock = 0;
int v = s;
do
if (UNDISCOVERED == status(v))
DFS(v, clock);
while (s != (v = (++v % n)));
}
template <typename Tv, typename Te>
void Graph<Tv, Te>::DFS(int v, int &clock)
{
dTime(v) = ++clock;
status(v) = DISCOVERED;
for (int u = firstNbr(v); -1 < u; u = nexNbr(v, u))
switch (status(u))
{
case UNDISCOVERED:
type(v, u) = TREE;
parent(u) = v;
DFS(u, clock);
break;
case DISCOVERED:
type(v, u) = BACKWARD;
break;
default:
type(v, u) = (dTime(v) < dTime(u)) ? FORWARD : CROSS;
break;
}
status(v) = VISITED;
fTime(v) = ++clock;
}
template <typename Tv, typename Te>
Stack<Tv> *Graph<Tv, Te>::tSort(int s)
{
reset();
int clock = 0;
int v = s;
Stack<Tv> *S = new Stack<Tv>;
do
{
if (UNDISCOVERED == status(v))
if (!TSort(v, clock, S))
{
while (!S->empty())
S->pop();
break;
}
} while (s != (v = (++v % n)));
return S;
}
template <typename Tv, typename Te>
bool Graph<Tv, Te>::TSort(int v, int &clock, Stack<Tv> *S)
{
dTime(v) = ++clock;
status(v) = DISCOVERED;
for (int u = firstNbr(v); -1 < u; u = nexNbr(v, u))
switch (status(u))
{
case UNDISCOVERED:
parent(u) = v;
type(v, u) = TREE;
if (!TSort(u, clock, S))
return false;
break;
case DISCOVERED:
type(v, u) = BACKWARD;
return false;
default:
type(v, u) = (dTime(v) < dTime(u)) ? FORWARD : CROSS;
break;
}
status(v) = VISITED;
S->push(vertex(v));
return true;
}