Professional Documents
Culture Documents
----------
CHAPTER 17. Graph Properties and Types
-----
struct Edge
{ int v, w;
Edge(int v = -1, int w = -1) : v(v), w(w) { }
};
class GRAPH
{ private:
// Implementation-dependent code
public:
GRAPH(int, bool);
~GRAPH();
int V() const;
int E() const;
bool directed() const;
int insert(Edge);
int remove(Edge);
bool edge(int, int);
class adjIterator
{
public:
adjIterator(const GRAPH &, int);
int beg();
int nxt();
bool end();
};
};
-----
template <class Graph>
vector <Edge> edges(Graph &G)
{ int E = 0;
vector <Edge> a(G.E());
for (int v = 0; v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (int w = A.beg(); !A.end(); w = A.nxt())
if (G.directed() || v < w)
a[E++] = Edge(v, w);
}
return a;
}
-----
template <class Graph>
void IO<Graph>::show(const Graph &G)
{
for (int s = 0; s < G.V(); s++)
{
cout.width(2); cout << s << ":";
typename Graph::adjIterator A(G, s);
for (int t = A.beg(); !A.end(); t = A.nxt())
{ cout.width(2); cout << t << " "; }
cout << endl;
}
}
-----
template <class Graph>
class IO
{
public:
static void show(const Graph &);
static void scanEZ(Graph &);
static void scan(Graph &);
};
-----
template <class Graph>
class CC
{
private:
// implementation-dependent code
public:
CC(const Graph &);
int count();
bool connect(int, int);
};
-----
#include <iostream.h>
#include <stdlib.h>
#include "GRAPH.cc"
#include "IO.cc"
#include "CC.cc"
main(int argc, char *argv[])
{ int V = atoi(argv[1]);
GRAPH G(V);
IO<GRAPH>::scan(G);
if (V < 20) IO<GRAPH>::show(G);
cout << G.E() << " edges ";
CC<GRAPH> Gcc(G);
cout << Gcc.count() << " components" << endl;
}
-----
class DenseGRAPH
{ int Vcnt, Ecnt; bool digraph;
vector <vector <bool> > adj;
public:
DenseGRAPH(int V, bool digraph = false) :
adj(V), Vcnt(V), Ecnt(0), digraph(digraph)
{
for (int i = 0; i < V; i++)
adj[i].assign(V, false);
}
int V() const { return Vcnt; }
int E() const { return Ecnt; }
bool directed() const { return digraph; }
void insert(Edge e)
{ int v = e.v, w = e.w;
if (adj[v][w] == false) Ecnt++;
adj[v][w] = true;
if (!digraph) adj[w][v] = true;
}
void remove(Edge e)
{ int v = e.v, w = e.w;
if (adj[v][w] == true) Ecnt--;
adj[v][w] = false;
if (!digraph) adj[w][v] = false;
}
bool edge(int v, int w) const
{ return adj[v][w]; }
class adjIterator;
friend class adjIterator;
};
-----
class DenseGRAPH::adjIterator
{ const DenseGRAPH &G;
int i, v;
public:
adjIterator(const DenseGRAPH &G, int v) :
G(G), v(v), i(-1) { }
int beg()
{ i = -1; return nxt(); }
int nxt()
{
for (i++; i < G.V(); i++)
if (G.adj[v][i] == true) return i;
return -1;
}
bool end()
{ return i >= G.V(); }
};
-----
class SparseMultiGRAPH
{ int Vcnt, Ecnt; bool digraph;
struct node
{ int v; node* next;
node(int x, node* t) { v = x; next = t; }
};
typedef node* link;
vector <link> adj;
public:
SparseMultiGRAPH(int V, bool digraph = false) :
adj(V), Vcnt(V), Ecnt(0), digraph(digraph)
{ adj.assign(V, 0); }
int V() const { return Vcnt; }
int E() const { return Ecnt; }
bool directed() const { return digraph; }
void insert(Edge e)
{ int v = e.v, w = e.w;
adj[v] = new node(w, adj[v]);
if (!digraph) adj[w] = new node(v, adj[w]);
Ecnt++;
}
void remove(Edge e);
bool edge(int v, int w) const;
class adjIterator;
friend class adjIterator;
};
-----
class SparseMultiGRAPH::adjIterator
{ const SparseMultiGRAPH &G;
int v;
link t;
public:
adjIterator(const SparseMultiGRAPH &G, int v) :
G(G), v(v) { t = 0; }
int beg()
{ t = G.adj[v]; return t ? t->v : -1; }
int nxt()
{ if (t) t = t->next; return t ? t->v : -1; }
bool end()
{ return t == 0; }
};
-----
template <class Graph> class DEGREE
{ const Graph &G;
vector <int> degree;
public:
DEGREE(const Graph &G) : G(G), degree(G.V(), 0)
{
for (int v = 0; v < G.V(); v++)
{ typename Graph::adjIterator A(G, v);
for (int w = A.beg(); !A.end(); w = A.nxt())
degree[v]++;
}
}
int operator[](int v) const
{ return degree[v]; }
};
-----
static void randE(Graph &G, int E)
{
for (int i = 0; i < E; i++)
{
int v = int(G.V()*rand()/(1.0+RAND_MAX));
int w = int(G.V()*rand()/(1.0+RAND_MAX));
G.insert(Edge(v,w));
}
}
-----
static void randG(Graph &G, int E)
{ double p = 2.0*E/G.V()/(G.V()-1);
for (int i = 0; i < G.V(); i++)
for (int j = 0; j < i; j++)
if (rand() < p*RAND_MAX)
G.insert(Edge(i, j));
}
-----
#include "ST.cc"
template <class Graph>
void IO<Graph>::scan(Graph &G)
{ string v, w;
ST st;
while (cin >> v >> w)
G.insert(Edge(st.index(v), st.index(w)));
}
-----
#include <string>
class ST
{ int N, val;
struct node
{ int v, d; node* l, *m, *r;
node(int d) : v(-1), d(d), l(0), m(0), r(0) {}
};
typedef node* link;
link head;
link indexR(link h, const string &s, int w)
{ int i = s[w];
if (h == 0) h = new node(i);
if (i == 0)
{
if (h->v == -1) h->v = N++;
val = h->v;
return h;
}
if (i < h->d) h->l = indexR(h->l, s, w);
if (i == h->d) h->m = indexR(h->m, s, w+1);
if (i > h->d) h->r = indexR(h->r, s, w);
return h;
}
public:
ST() : head(0), N(0) { }
int index(const string &key)
{ head = indexR(head, key, 0); return val; }
};
-----
template <class Graph> class sPATH
{ const Graph &G;
vector <bool> visited;
bool found;
bool searchR(int v, int w)
{
if (v == w) return true;
visited[v] = true;
typename Graph::adjIterator A(G, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (!visited[t])
if (searchR(t, w)) return true;
return false;
}
public:
sPATH(const Graph &G, int v, int w) :
G(G), visited(G.V(), false)
{ found = searchR(v, w); }
bool exists() const
{ return found; }
};
-----
bool searchR(int v, int w, int d)
{
if (v == w) return (d == 0);
visited[v] = true;
typename Graph::adjIterator A(G, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (!visited[t])
if (searchR(t, w, d-1)) return true;
visited[v] = false;
return false;
}
-----
template <class Graph> class ePATH
{ Graph G;
int v, w;
bool found;
STACK <int> S;
int tour(int v);
public:
ePATH(const Graph &G, int v, int w) :
G(G), v(v), w(w)
{ DEGREE<Graph> deg(G);
int t = deg[v] + deg[w];
if ((t % 2) != 0) { found = false; return; }
for (t = 0; t < G.V(); t++)
if ((t != v) && (t != w))
if ((deg[t] % 2) != 0)
{ found = false; return; }
found = true;
}
bool exists() const
{ return found; }
void show();
};
-----
template <class Graph>
int ePATH<Graph>::tour(int v)
{
while (true)
{ typename Graph::adjIterator A(G, v);
int w = A.beg(); if (A.end()) break;
S.push(v);
G.remove(Edge(v, w));
v = w;
}
return v;
}
template <class Graph>
void ePATH<Graph>::show()
{
if (!found) return;
while (tour(v) == v && !S.empty())
{ v = S.pop(); cout << "-" << v; }
cout << endl;
}
----------
CHAPTER 18. Graph Search
-----
#include <vector>
template <class Graph> class cDFS
{ int cnt;
const Graph &G;
vector <int> ord;
void searchC(int v)
{
ord[v] = cnt++;
typename Graph::adjIterator A(G, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1) searchC(t);
}
public:
cDFS(const Graph &G, int v = 0) :
G(G), cnt(0), ord(G.V(), -1)
{ searchC(v); }
int count() const { return cnt; }
int operator[](int v) const { return ord[v]; }
};
-----
template <class Graph> class SEARCH
{
protected:
const Graph &G;
int cnt;
vector <int> ord;
virtual void searchC(Edge) = 0;
void search()
{ for (int v = 0; v < G.V(); v++)
if (ord[v] == -1) searchC(Edge(v, v)); }
public:
SEARCH (const Graph &G) : G(G),
ord(G.V(), -1), cnt(0) { }
int operator[](int v) const { return ord[v]; }
};
-----
template <class Graph>
class DFS : public SEARCH<Graph>
{ vector<int> st;
void searchC(Edge e)
{ int w = e.w;
ord[w] = cnt++; st[e.w] = e.v;
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1) searchC(Edge(w, t));
}
public:
DFS(const Graph &G) : SEARCH<Graph>(G),
st(G.V(), -1) { search(); }
int ST(int v) const { return st[v]; }
};
-----
template <class Graph> class CC
{ const Graph &G;
int ccnt;
vector <int> id;
void ccR(int w)
{
id[w] = ccnt;
typename Graph::adjIterator A(G, w);
for (int v = A.beg(); !A.end(); v = A.nxt())
if (id[v] == -1) ccR(v);
}
public:
CC(const Graph &G) : G(G), ccnt(0), id(G.V(), -1)
{
for (int v = 0; v < G.V(); v++)
if (id[v] == -1) { ccR(v); ccnt++; }
}
int count() const { return ccnt; }
bool connect(int s, int t) const
{ return id[s] == id[t]; }
};
-----
template <class Graph>
class EULER : public SEARCH<Graph>
{
void searchC(Edge e)
{ int v = e.v, w = e.w;
ord[w] = cnt++;
cout << "-" << w;
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1) searchC(Edge(w, t));
else if (ord[t] < ord[v])
cout << "-" << t << "-" << w;
if (v != w) cout << "-" << v; else cout << endl;
}
public:
EULER(const Graph &G) : SEARCH<Graph>(G)
{ search(); }
};
-----
template <class Graph> class BI
{ const Graph &G;
bool OK;
vector <int> vc;
bool dfsR(int v, int c)
{
vc[v] = (c+1) %2;
typename Graph::adjIterator A(G, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (vc[t] == -1)
{ if (!dfsR(t, vc[v])) return false; }
else if (vc[t] != c) return false;
return true;
}
public:
BI(const Graph &G) : G(G), OK(true), vc(G.V(),-1)
{
for (int v = 0; v < G.V(); v++)
if (vc[v] == -1)
if (!dfsR(v, 0)) { OK = false; return; }
}
bool bipartite() const { return OK; }
int color(int v) const { return vc[v]; }
};
-----
template <class Graph>
class EC : public SEARCH<Graph>
{ int bcnt;
vector <int> low;
void searchC(Edge e)
{ int w = e.w;
ord[w] = cnt++; low[w] = ord[w];
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1)
{
searchC(Edge(w, t));
if (low[w] > low[t]) low[w] = low[t];
if (low[t] == ord[t])
bcnt++; // w-t is a bridge
}
else if (t != e.v)
if (low[w] > ord[t]) low[w] = ord[t];
}
public:
EC(const Graph &G) : SEARCH<Graph>(G),
bcnt(0), low(G.V(), -1)
{ search(); }
int count() const { return bcnt+1; }
};
-----
#include "QUEUE.cc"
template <class Graph>
class BFS : public SEARCH<Graph>
{ vector<int> st;
void searchC(Edge e)
{ QUEUE<Edge> Q;
Q.put(e);
while (!Q.empty())
if (ord[(e = Q.get()).w] == -1)
{ int v = e.v, w = e.w;
ord[w] = cnt++; st[w] = v;
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1) Q.put(Edge(w, t));
}
}
public:
BFS(Graph &G) : SEARCH<Graph>(G), st(G.V(), -1)
{ search(); }
int ST(int v) const { return st[v]; }
};
-----
void searchC(Edge e)
{ QUEUE<Edge> Q;
Q.put(e); ord[e.w] = cnt++;
while (!Q.empty())
{
e = Q.get(); st[e.w] = e.v;
typename Graph::adjIterator A(G, e.w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1)
{ Q.put(Edge(e.w, t)); ord[t] = cnt++; }
}
}
-----
#include "GQ.cc"
template <class Graph>
class PFS : public SEARCH<Graph>
{ vector<int> st;
void searchC(Edge e)
{ GQ<Edge> Q(G.V());
Q.put(e); ord[e.w] = cnt++;
while (!Q.empty())
{
e = Q.get(); st[e.w] = e.v;
typename Graph::adjIterator A(G, e.w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (ord[t] == -1)
{ Q.put(Edge(e.w, t)); ord[t] = cnt++; }
else
if (st[t] == -1) Q.update(Edge(e.w, t));
}
}
public:
PFS(Graph &G) : SEARCH<Graph>(G), st(G.V(), -1)
{ search(); }
int ST(int v) const { return st[v]; }
};
-----
template <class Item>
class GQ
{
private:
vector<Item> s; int N;
public:
GQ(int maxN) : s(maxN+1), N(0) { }
int empty() const
{ return N == 0; }
void put(Item item)
{ s[N++] = item; }
void update(Item x) { }
Item get()
{ int i = int(N*rand()/(1.0+RAND_MAX));
Item t = s[i];
s[i] = s[N-1];
s[N-1] = t;
return s[--N]; }
};
----------
CHAPTER 19. Digraphs and DAGs
-----
template <class inGraph, class outGraph>
void reverse(const inGraph &G, outGraph &R)
{
for (int v = 0; v < G.V(); v++)
{ typename inGraph::adjIterator A(G, v);
for (int w = A.beg(); !A.end(); w = A.nxt())
R.insert(Edge(w, v));
}
}
-----
template <class Graph> class DFS
{ const Graph &G;
int depth, cnt, cntP;
vector<int> pre, post;
void show(char *s, Edge e)
{ for (int i = 0; i < depth; i++) cout << " ";
cout << e.v << "-" << e.w << s << endl; }
void dfsR(Edge e)
{ int w = e.w; show(" tree", e);
pre[w] = cnt++; depth++;
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
{ Edge x(w, t);
if (pre[t] == -1) dfsR(x);
else if (post[t] == -1) show(" back", x);
else if (pre[t] > pre[w]) show(" down", x);
else show(" cross", x);
}
post[w] = cntP++; depth--;
}
public:
DFS(const Graph &G) : G(G), cnt(0), cntP(0),
pre(G.V(), -1), post(G.V(), -1)
{ for (int v = 0; v < G.V(); v++)
if (pre[v] == -1) dfsR(Edge(v, v)); }
};
-----
template <class tcGraph, class Graph> class TC
{ tcGraph T;
public:
TC(const Graph &G) : T(G)
{
for (int s = 0; s < T.V(); s++)
T.insert(Edge(s, s));
for (int i = 0; i < T.V(); i++)
for (int s = 0; s < T.V(); s++)
if (T.edge(s, i))
for (int t = 0; t < T.V(); t++)
if (T.edge(i, t))
T.insert(Edge(s, t));
}
bool reachable(int s, int t) const
{ return T.edge(s, t); }
};
-----
template <class Graph> class tc
{ Graph T; const Graph &G;
void tcR(int v, int w)
{
T.insert(Edge(v, w));
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (!T.edge(v, t)) tcR(v, t);
}
public:
tc(const Graph &G) : G(G), T(G.V(), true)
{ for (int v = 0; v < G.V(); v++) tcR(v, v); }
bool reachable(int v, int w)
{ return T.edge(v, w); }
};
-----
int compressR(link h)
{ STx st;
if (h == NULL) return 0;
l = compressR(h->l);
r = compressR(h->r);
t = st.index(l, r);
adj[t].l = l; adj[t].r = r;
return t;
}
-----
template <class Dag> class dagTS
{ const Dag &D;
int cnt, tcnt;
vector<int> pre, post, postI;
void tsR(int v)
{
pre[v] = cnt++;
typename Dag::adjIterator A(D, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (pre[t] == -1) tsR(t);
post[v] = tcnt; postI[tcnt++] = v;
}
public:
dagTS(const Dag &D) : D(D), tcnt(0), cnt(0),
pre(D.V(), -1), post(D.V(), -1), postI(D.V(), -1)
{ for (int v = 0; v < D.V(); v++)
if (pre[v] == -1) tsR(v); }
int operator[](int v) const { return postI[v]; }
int relabel(int v) const { return post[v]; }
};
-----
void tsR(int v)
{
pre[v] = cnt++;
for (int w = 0; w < D.V(); w++)
if (D.edge(w, v))
if (pre[w] == -1) tsR(w);
post[v] = tcnt; postI[tcnt++] = v;
}
-----
#include "QUEUE.cc"
template <class Dag> class dagTS
{ const Dag &D;
vector<int> in, ts, tsI;
public:
dagTS(const Dag &D) : D(D),
in(D.V(), 0), ts(D.V(), -1), tsI(D.V(), -1)
{ QUEUE<int> Q;
for (int v = 0; v < D.V(); v++)
{
typename Dag::adjIterator A(D, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
in[t]++;
}
for (int v = 0; v < D.V(); v++)
if (in[v] == 0) Q.put(v);
for (int j = 0; !Q.empty(); j++)
{
ts[j] = Q.get(); tsI[ts[j]] = j;
typename Dag::adjIterator A(D, ts[j]);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (--in[t] == 0) Q.put(t);
}
}
int operator[](int v) const { return ts[v]; }
int relabel(int v) const { return tsI[v]; }
};
-----
template <class tcDag, class Dag> class dagTC
{ tcDag T; const Dag &D;
int cnt;
vector<int> pre;
void tcR(int w)
{
pre[w] = cnt++;
typename Dag::adjIterator A(D, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
{
T.insert(Edge(w, t));
if (pre[t] > pre[w]) continue;
if (pre[t] == -1) tcR(t);
for (int i = 0; i < T.V(); i++)
if (T.edge(t, i)) T.insert(Edge(w, i));
}
}
public:
dagTC(const Dag &D) : D(D), cnt(0),
pre(D.V(), -1), T(D.V(), true)
{ for (int v = 0; v < D.V(); v++)
if (pre[v] == -1) tcR(v); }
bool reachable(int v, int w) const
{ return T.edge(v, w); }
};
-----
template <class Graph> class SC
{ const Graph &G;
int cnt, scnt;
vector<int> postI, postR, id;
void dfsR(const Graph &G, int w)
{
id[w] = scnt;
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (id[t] == -1) dfsR(G, t);
postI[cnt++] = w;
}
public:
SC(const Graph &G) : G(G), cnt(0), scnt(0),
postI(G.V()), postR(G.V()), id(G.V(), -1)
{ Graph R(G.V(), true);
reverse(G, R);
for (int v = 0; v < R.V(); v++)
if (id[v] == -1) dfsR(R, v);
postR = postI; cnt = scnt = 0;
id.assign(G.V(), -1);
for (int v = G.V()-1; v >= 0; v--)
if (id[postR[v]] == -1)
{ dfsR(G, postR[v]); scnt++; }
}
int count() const { return scnt; }
bool stronglyreachable(int v, int w) const
{ return id[v] == id[w]; }
};
-----
#include "STACK.cc"
template <class Graph> class SC
{ const Graph &G;
STACK<int> S;
int cnt, scnt;
vector<int> pre, low, id;
void scR(int w)
{ int t;
int min = low[w] = pre[w] = cnt++;
S.push(w);
typename Graph::adjIterator A(G, w);
for (t = A.beg(); !A.end(); t = A.nxt())
{
if (pre[t] == -1) scR(t);
if (low[t] < min) min = low[t];
}
if (min < low[w]) { low[w] = min; return; }
do
{ id[t = S.pop()] = scnt; low[t] = G.V(); }
while (t != w);
scnt++;
}
public:
SC(const Graph &G) : G(G), cnt(0), scnt(0),
pre(G.V(), -1), low(G.V()), id(G.V())
{ for (int v = 0; v < G.V(); v++)
if (pre[v] == -1) scR(v); }
int count() const { return scnt; }
bool stronglyreachable(int v, int w) const
{ return id[v] == id[w]; }
};
-----
void scR(int w)
{ int v;
pre[w] = cnt++;
S.push(w); path.push(w);
typename Graph::adjIterator A(G, w);
for (int t = A.beg(); !A.end(); t = A.nxt())
if (pre[t] == -1) scR(t);
else if (id[t] == -1)
while (pre[path.top()] > pre[t]) path.pop();
if (path.top() == w) path.pop(); else return;
do { id[v = S.pop()] = scnt; } while (v != w);
scnt++;
}
-----
template <class Graph> class TC
{ const Graph &G; DenseGRAPH *K;
dagTC<DenseGRAPH, Graph> *Ktc;
SC<Graph> *Gsc;
public:
TC(const Graph &G) : G(G)
{
Gsc = new SC<Graph>(G);
K = new DenseGRAPH(Gsc->count(), true);
for (int v = 0; v < G.V(); v++)
{ typename Graph::adjIterator A(G, v);
for (int t = A.beg(); !A.end(); t = A.nxt())
K->insert(Edge(Gsc->ID(v), Gsc->ID(t))); }
Ktc = new dagTC<DenseGRAPH, Graph>(*K);
}
~TC() { delete K; delete Ktc; delete Gsc; }
bool reachable(int v, int w)
{ return Ktc->reachable(Gsc->ID(v), Gsc->ID(w));}
};
----------
CHAPTER 20. Minimum Spanning Trees
-----
class EDGE
{
public:
EDGE(int, int, double);
int v() const;
int w() const;
double wt() const;
bool from(int) const;
int other(int) const;
};
template <class Edge> class GRAPH
{
public:
GRAPH(int, bool);
~GRAPH();
int V() const;
int E() const;
bool directed() const;
int insert(Edge *);
int remove(Edge *);
Edge *edge(int, int);
class adjIterator
{
public:
adjIterator(const GRAPH &, int);
Edge *beg();
Edge *nxt();
bool end();
};
};
-----
template <class Graph, class Edge>
vector <Edge *> edges(const Graph &G)
{ int E = 0;
vector <Edge *> a(G.E());
for (int v = 0; v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
if (e->from(v)) a[E++] = e;
}
return a;
}
-----
template <class Edge> class DenseGRAPH
{ int Vcnt, Ecnt; bool digraph;
vector <vector <Edge *> > adj;
public:
DenseGRAPH(int V, bool digraph = false) :
adj(V), Vcnt(V), Ecnt(0), digraph(digraph)
{
for (int i = 0; i < V; i++)
adj[i].assign(V, 0);
}
int V() const { return Vcnt; }
int E() const { return Ecnt; }
bool directed() const { return digraph; }
void insert(Edge *e)
{ int v = e->v(), w = e->w();
if (adj[v][w] == 0) Ecnt++;
adj[v][w] = e;
if (!digraph) adj[w][v] = e;
}
void remove(Edge *e)
{ int v = e->v(), w = e->w();
if (adj[v][w] != 0) Ecnt--;
adj[v][w] = 0;
if (!digraph) adj[w][v] = 0;
}
Edge* edge(int v, int w) const
{ return adj[v][w]; }
class adjIterator;
friend class adjIterator;
};
-----
template <class Edge>
class DenseGRAPH<Edge>::adjIterator
{ const DenseGRAPH<Edge> &G;
int i, v;
public:
adjIterator(const DenseGRAPH<Edge> &G, int v) :
G(G), v(v), i(0) { }
Edge *beg()
{ i = -1; return nxt(); }
Edge *nxt()
{
for (i++; i < G.V(); i++)
if (G.edge(v, i)) return G.adj[v][i];
return 0;
}
bool end() const
{ return i >= G.V(); }
};
-----
template <class Edge> class SparseMultiGRAPH
{ int Vcnt, Ecnt; bool digraph;
struct node
{ Edge* e; node* next;
node(Edge* e, node* next): e(e), next(next) {}
};
typedef node* link;
vector <link> adj;
public:
SparseMultiGRAPH(int V, bool digraph = false) :
adj(V), Vcnt(V), Ecnt(0), digraph(digraph) { }
int V() const { return Vcnt; }
int E() const { return Ecnt; }
bool directed() const { return digraph; }
void insert(Edge *e)
{
adj[e->v()] = new node(e, adj[e->v()]);
if (!digraph)
adj[e->w()] = new node(e, adj[e->w()]);
Ecnt++;
}
class adjIterator;
friend class adjIterator;
};
-----
template <class Graph, class Edge> class MST
{ const Graph &G;
vector<double> wt;
vector<Edge *> fr, mst;
public:
MST(const Graph &G) : G(G),
mst(G.V()), wt(G.V(), G.V()), fr(G.V())
{ int min = -1;
for (int v = 0; min != 0; v = min)
{
min = 0;
for (int w = 1; w < G.V(); w++)
if (mst[w] == 0)
{ double P; Edge* e = G.edge(v, w);
if (e)
if ((P = e->wt()) < wt[w])
{ wt[w] = P; fr[w] = e; }
if (wt[w] < wt[min]) min = w;
}
if (min) mst[min] = fr[min];
}
}
void show()
{ for (int v = 1; v < G.V(); v++)
if (mst[v]) mst[v]->show();}
};
-----
template <class Graph, class Edge> class MST
{ const Graph &G;
vector<double> wt;
vector<Edge *> fr, mst;
void pfs(int s)
{ PQi<double> pQ(G.V(), wt);
pQ.insert(s);
while (!pQ.empty())
{ int v = pQ.getmin();
mst[v] = fr[v];
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ double P = e->wt(); int w = e->other(v);
if (fr[w] == 0)
{ wt[w] = P; pQ.insert(w); fr[w] = e; }
else if (mst[w] == 0 && P < wt[w])
{ wt[w] = P; pQ.lower(w); fr[w] = e; }
}
}
}
public:
MST(Graph &G) : G(G),
fr(G.V()), mst(G.V()), wt(G.V(), -1)
{ for (int v = 0; v < G.V(); v++)
if (mst[v] == 0) pfs(v); }
};
-----
template <class Graph, class Edge, class EdgePtr>
class MST
{ const Graph &G;
vector<EdgePtr> a, mst;
UF uf;
public:
MST(Graph &G) : G(G), uf(G.V()), mst(G.V())
{ int V = G.V(), E = G.E();
a = edges<Graph, Edge, EdgePtr>(G);
sort<EdgePtr>(a, 0, E-1);
for (int i = 0, k = 1; i < E && k < V; i++)
if (!uf.find(a[i]->v, a[i]->w))
{ uf.unite(a[i]->v, a[i]->w);
mst[k++] = a[i]; }
}
};
-----
template <class Graph, class Edge> class MST
{ const Graph &G;
vector<Edge *> a, b, mst;
UF uf;
public:
MST(const Graph &G): G(G), uf(G.V()), mst(G.V()+1)
{ a = edges<Graph, Edge>(G);
int N, k = 1;
for (int E = a.size(); E != 0; E = N)
{ int h, i, j;
b.assign(G.V(), 0);
for (h = 0, N = 0; h < E; h++)
{ Edge *e = a[h];
i = uf.find(e->v()), j = uf.find(e->w());
if (i == j) continue;
if (!b[i] || e->wt() < b[i]->wt()) b[i] = e;
if (!b[j] || e->wt() < b[j]->wt()) b[j] = e;
a[N++] = e;
}
for (h = 0; h < G.V(); h++)
if (b[h])
if (!uf.find(i = b[h]->v(), j = b[h]->w()))
{ uf.unite(i, j); mst[k++] = b[h]; }
}
}
};
-----
template <class keyType> class PQi
{ int d, N;
vector<int> pq, qp;
const vector<keyType> &a;
void exch(int i, int j)
{ int t = pq[i]; pq[i] = pq[j]; pq[j] = t;
qp[pq[i]] = i; qp[pq[j]] = j; }
void fixUp(int k)
{ while (k > 1 && a[pq[(k+d-2)/d]] > a[pq[k]])
{ exch(k, (k+d-2)/d); k = (k+d-2)/d; } }
void fixDown(int k, int N)
{ int j;
while ((j = d*(k-1)+2) <= N)
{
for (int i = j+1; i < j+d && i <= N; i++)
if (a[pq[j]] > a[pq[i]]) j = i;
if (!(a[pq[k]] > a[pq[j]])) break;
exch(k, j); k = j;
}
}
public:
PQi(int N, const vector<keyType> &a, int d = 3) :
a(a), pq(N+1, 0), qp(N+1, 0), N(0), d(d) { }
int empty() const { return N == 0; }
void insert(int v)
{ pq[++N] = v; qp[v] = N; fixUp(N); }
int getmin()
{ exch(1, N); fixDown(1, N-1); return pq[N--]; }
void lower(int k)
{ fixUp(qp[k]); }
};
----------
CHAPTER 21. Shortest Paths
-----
template <class Graph, class Edge> class SPT
{ const Graph &G;
vector<double> wt;
vector<Edge *> spt;
public:
SPT(const Graph &G, int s) : G(G),
spt(G.V()), wt(G.V(), G.V())
{ PQi<double> pQ(G.V(), wt);
for (int v = 0; v < G.V(); v++) pQ.insert(v);
wt[s] = 0.0; pQ.lower(s);
while (!pQ.empty())
{ int v = pQ.getmin(); // wt[v] = 0.0;
if (v != s && spt[v] == 0) return;
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ int w = e->w();
double P = wt[v] + e->wt();
if (P < wt[w])
{ wt[w] = P; pQ.lower(w); spt[w] = e; }
}
}
}
Edge *pathR(int v) const { return spt[v]; }
double dist(int v) const { return wt[v]; }
};
-----
template <class Graph, class Edge> class SPall
{
public:
SPall(const Graph &);
Edge *path(int, int) const;
Edge *pathR(int, int) const;
double dist(int, int) const;
};
-----
template <class Graph, class Edge>
double diameter(Graph &G)
{ int vmax = 0, wmax = 0;
allSP<Graph, Edge> all(G);
for (int v = 0; v < G.V(); v++)
for (int w = 0; w < G.V(); w++)
if (all.path(v, w))
if (all.dist(v, w) > all.dist(vmax, wmax))
{ vmax = v; wmax = w; }
int v = vmax; cout << v;
while (v != wmax)
{ v = all.path(v, wmax)->w(); cout << "-" << v; }
return all.dist(vmax, wmax);
}
-----
#include "SPT.cc"
template <class Graph, class Edge> class allSP
{ const Graph &G;
vector< SPT<Graph, Edge> *> A;
public:
allSP(const Graph &G) : G(G), A(G.V())
{ for (int s = 0; s < G.V(); s++)
A[s] = new SPT<Graph, Edge>(G, s); }
Edge *pathR(int s, int t) const
{ return A[s]->pathR(t); }
double dist(int s, int t) const
{ return A[s]->dist(t); }
};
-----
template <class Graph, class Edge> class allSP
{ const Graph &G;
vector <vector <Edge *> > p;
vector <vector <double> > d;
public:
allSP(const Graph &G) : G(G), p(G.V()), d(G.V())
{ int V = G.V();
for (int i = 0; i < V; i++)
{ p[i].assign(V, 0); d[i].assign(V, V); }
for (int s = 0; s < V; s++)
for (int t = 0; t < V; t++)
if (G.edge(s, t))
{ p[s][t] = G.edge(s, t);
d[s][t] = G.edge(s, t)->wt(); }
for (int s = 0; s < V; s++) d[s][s] = 0;
for (int i = 0; i < V; i++)
for (int s = 0; s < V; s++)
if (p[s][i])
for (int t = 0; t < V; t++)
if (s != t)
if (d[s][t] > d[s][i] + d[i][t])
{ p[s][t] = p[s][i];
d[s][t] = d[s][i] + d[i][t]; }
}
Edge *path(int s, int t) const
{ return p[s][t]; }
double dist(int s, int t) const
{ return d[s][t]; }
};
-----
#include "dagTS.cc"
template <class Graph, class Edge> class LPTdag
{ const Graph &G;
vector<double> wt;
vector<Edge *> lpt;
public:
LPTdag(const Graph &G) : G(G),
lpt(G.V()), wt(G.V(), 0)
{ int j, w;
dagTS<Graph> ts(G);
for (int v = ts[j = 0]; j < G.V(); v = ts[++j])
{ typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
if (wt[w = e->w()] < wt[v] + e->wt())
{ wt[w] = wt[v] + e->wt(); lpt[w] = e; }
}
}
Edge *pathR(int v) const { return lpt[v]; }
double dist(int v) const { return wt[v]; }
};
-----
template <class Graph, class Edge> class allSPdag
{ const Graph &G;
vector <vector <Edge *> > p;
vector <vector <double> > d;
void dfsR(int s)
{ typename Graph::adjIterator A(G, s);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ int t = e->w(); double w = e->wt();
if (d[s][t] > w)
{ d[s][t] = w; p[s][t] = e; }
if (p[t][t] == 0) dfsR(t);
for (int i = 0; i < G.V(); i++)
if (p[t][i])
if (d[s][i] > w + d[t][i])
{ d[s][i] = w + d[t][i]; p[s][i] = e; }
}
}
public:
allSPdag(const Graph &G) : G(G),
p(G.V()), d(G.V())
{ int V = G.V();
for (int i = 0; i < V; i++)
{ p[i].assign(V, 0); d[i].assign(V, V); }
for (int s = 0; s < V; s++)
if (p[s][s] == 0) dfsR(s);
}
Edge *path(int s, int t) const
{ return p[s][t]; }
double dist(int s, int t) const
{ return d[s][t]; }
};
-----
#include "GRAPHbasic.cc"
#include "GRAPHio.cc"
#include "LPTdag.cc"
typedef WeightedEdge EDGE;
typedef DenseGRAPH<EDGE> GRAPH;
int main(int argc, char *argv[])
{ int i, s, t, N = atoi(argv[1]);
double duration[N];
GRAPH G(N, true);
for (int i = 0; i < N; i++)
cin >> duration[i];
while (cin >> s >> t)
G.insert(new EDGE(s, t, duration[s]));
LPTdag<GRAPH, EDGE> lpt(G);
for (i = 0; i < N; i++)
cout << i << " " << lpt.dist(i) << endl;
}
-----
SPT(Graph &G, int s) : G(G),
spt(G.V()), wt(G.V(), G.V())
{ QUEUE<int> Q; int N = 0;
wt[s] = 0.0;
Q.put(s); Q.put(G.V());
while (!Q.empty())
{ int v;
while ((v = Q.get()) == G.V())
{ if (N++ > G.V()) return; Q.put(G.V()); }
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ int w = e->w();
double P = wt[v] + e->wt();
if (P < wt[w])
{ wt[w] = P; Q.put(w); spt[w] = e; }
}
}
}
----------
CHAPTER 22. Network Flow
-----
template <class Graph, class Edge> class check
{
public:
static int flow(Graph &G, int v)
{ int x = 0;
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
x += e->from(v) ? e->flow() : -e->flow();
return x;
}
static bool flow(Graph &G, int s, int t)
{
for (int v = 0; v < G.V(); v++)
if ((v != s) && (v != t))
if (flow(G, v) != 0) return false;
int sflow = flow(G, s);
if (sflow < 0) return false;
if (sflow + flow(G, t) != 0) return false;
return true;
}
};
-----
class EDGE
{ int pv, pw, pcap, pflow;
public:
EDGE(int v, int w, int cap) :
pv(v), pw(w), pcap(cap), pflow(0) { }
int v() const { return pv; }
int w() const { return pw; }
int cap() const { return pcap; }
int flow() const { return pflow; }
bool from (int v) const
{ return pv == v; }
int other(int v) const
{ return from(v) ? pw : pv; }
int capRto(int v) const
{ return from(v) ? pflow : pcap - pflow; }
void addflowRto(int v, int d)
{ pflow += from(v) ? -d : d; }
};
-----
template <class Graph, class Edge> class MAXFLOW
{ const Graph &G;
int s, t;
vector<int> wt;
vector<Edge *> st;
int ST(int v) const { return st[v]->other(v); }
void augment(int s, int t)
{ int d = st[t]->capRto(t);
for (int v = ST(t); v != s; v = ST(v))
if (st[v]->capRto(v) < d)
d = st[v]->capRto(v);
st[t]->addflowRto(t, d);
for (int v = ST(t); v != s; v = ST(v))
st[v]->addflowRto(v, d);
}
bool pfs();
public:
MAXFLOW(const Graph &G, int s, int t) : G(G),
s(s), t(t), st(G.V()), wt(G.V())
{ while (pfs()) augment(s, t); }
};
-----
template <class Graph, class Edge>
bool MAXFLOW<Graph, Edge>::pfs()
{ PQi<int> pQ(G.V(), wt);
for (int v = 0; v < G.V(); v++)
{ wt[v] = 0; st[v] = 0; pQ.insert(v); }
wt[s] = -M; pQ.lower(s);
while (!pQ.empty())
{ int v = pQ.getmin(); wt[v] = -M;
if (v == t || (v != s && st[v] == 0)) break;
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ int w = e->other(v);
int cap = e->capRto(w);
int P = cap < -wt[v] ? cap : -wt[v];
if (cap > 0 && -P < wt[w])
{ wt[w] = -P; pQ.lower(w); st[w] = e; }
}
}
return st[t] != 0;
}
-----
template <class Graph, class Edge> class MAXFLOW
{ const Graph &G;
int s, t;
vector<int> h, wt;
void initheights();
public:
MAXFLOW(const Graph &G, int s, int t) : G(G),
s(s), t(t), h(G.V()), wt(G.V(), 0)
{ initheights();
GQ gQ(G.V());
gQ.put(s); wt[t] = -(wt[s] = M*G.V());
while (!gQ.empty())
{ int v = gQ.get();
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
{ int w = e->other(v);
int cap = e->capRto(w);
int P = cap < wt[v] ? cap : wt[v];
if (P > 0 && v == s || h[v] == h[w]+1)
{ e->addflowRto(w, P);
wt[v] -= P; wt[w] += P;
if ((w != s) && (w != t)) gQ.put(w); }
}
if (v != s && v != t && wt[v] > 0)
{ h[v]++; gQ.put(v); }
}
}
};
-----
#include "MAXFLOW.cc"
template <class Graph, class Edge> class FEASIBLE
{ const Graph &G;
void freeedges(const Graph &F, int v)
{ typename Graph::adjIterator A(F, v);
for (EDGE* e = A.beg(); !A.end(); e = A.nxt())
delete e;
}
public:
FEASIBLE(const Graph &G, vector<int> sd) : G(G)
{
Graph F(G.V()+2);
for (int v = 0; v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (EDGE* e = A.beg(); !A.end(); e = A.nxt())
F.insert(e);
}
int s = G.V(), t = G.V()+1;
for (int i = 0; i < G.V(); i++)
if (sd[i] >= 0)
F.insert(new EDGE(s, i, sd[i]));
else
F.insert(new EDGE(i, t, -sd[i]));
MAXFLOW<Graph, Edge>(F, s, t);
freeedges(F, s); freeedges(F, t);
}
};
-----
#include "GRAPHbasic.cc"
#include "MAXFLOW.cc"
int main(int argc, char *argv[])
{ int s, t, N = atoi(argv[1]);
GRAPH<EDGE> G(2*N+2);
for (int i = 0; i < N; i++)
G.insert(new EDGE(2*N, i, 1));
while (cin >> s >> t)
G.insert(new EDGE(s, t, 1));
for (int i = N; i < 2*N; i++)
G.insert(new EDGE(i, 2*N+1, 1));
MAXFLOW<GRAPH<EDGE>, EDGE>(G, 2*N, 2*N+1);
for (int i = 0; i < N; i++)
{
GRAPH<EDGE>::adjIterator A(G, i);
for (EDGE* e = A.beg(); !A.end(); e = A.nxt())
if (e->flow() == 1 && e->from(i))
cout << e->v() << "-" << e->w() << endl;
}
}
-----
static int cost(Graph &G)
{ int x = 0;
for (int v = 0; v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
if (e->from(v) && e->costRto(e->w()) < C)
x += e->flow()*e->costRto(e->w());
}
return x;
}
-----
template <class Graph, class Edge> class MINCOST
{ const Graph &G;
int s, t;
vector<int> wt;
vector <Edge *> st;
int ST(int v) const;
void augment(int, int);
int negcyc(int);
int negcyc();
public:
MINCOST(const Graph &G, int s, int t) : G(G),
s(s), t(t), st(G.V()), wt(G.V())
{ MAXFLOW<Graph, Edge>(G, s, t);
for (int x = negcyc(); x != -1; x = negcyc())
{ augment(x, x); }
}
};
-----
int phiR(int v)
{
if (mark[v] == valid) return phi[v];
phi[v] = phiR(ST(v)) - st[v]->costRto(v);
mark[v] = valid;
return phi[v];
}
-----
int lca(int v, int w)
{ mark[v] = ++valid; mark[w] = valid;
while (v != w)
{
if (v != t) v = ST(v);
if (v != t && mark[v] == valid) return v;
mark[v] = valid;
if (w != t) w = ST(w);
if (w != t && mark[w] == valid) return w;
mark[w] = valid;
}
return v;
}
Edge *augment(Edge *x)
{ int v = x->v(), w = x->w(); int r = lca(v, w);
int d = x->capRto(w);
for (int u = w; u != r; u = ST(u))
if (st[u]->capRto(ST(u)) < d)
d = st[u]->capRto(ST(u));
for (int u = v; u != r; u = ST(u))
if (st[u]->capRto(u) < d)
d = st[u]->capRto(u);
x->addflowRto(w, d); Edge* e = x;
for (int u = w; u != r; u = ST(u))
{ st[u]->addflowRto(ST(u), d);
if (st[u]->capRto(ST(u)) == 0) e = st[u]; }
for (int u = v; u != r; u = ST(u))
{ st[u]->addflowRto(u, d);
if (st[u]->capRto(u) == 0) e = st[u]; }
return e;
}
-----
bool onpath(int a, int b, int c)
{
for (int i = a; i != c; i = ST(i))
if (i == b) return true;
return false;
}
void reverse(int u, int x)
{ Edge *e = st[u];
for (int i = ST(u); i != x; i = ST(i))
{ Edge *y = st[i]; st[i] = e; e = y; }
}
void update(Edge *w, Edge *y)
{ int u = y->w(), v = y->v(), x = w->w();
if (st[x] != w) x = w->v();
int r = lca(u, v);
if (onpath(u, x, r))
{ reverse(u, x); st[u] = y; return; }
if (onpath(v, x, r))
{ reverse(v, x); st[v] = y; return; }
}
-----
int costR(Edge *e, int v)
{ int R = e->cost() + phi[e->w()] - phi[e->v()];
return e->from(v) ? R : -R; }
Edge *besteligible()
{ Edge *x = 0;
for (int v = 0, min = C*G.V(); v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
if (e->capRto(e->other(v)) > 0)
if (e->capRto(v) == 0)
if (costR(e, v) < min)
{ x = e; min = costR(e, v); }
}
return x;
}
-----
template <class Graph, class Edge> class MINCOST
{ const Graph &G; int s, t; int valid;
vector<Edge *> st; vector<int> mark, phi;
void dfsR(Edge);
int ST(int);
int phiR(int);
int lca(int, int); Edge *augment(Edge *);
bool onpath(int, int, int);
void reverse(int, int);
void update(Edge *, Edge *);
int costR(Edge *, int); Edge *besteligible();
public:
MINCOST(Graph &G, int s, int t) : G(G), s(s), t(t)
st(G.V()), mark(G.V(), -1), phi(G.V())
{
Edge *z = new EDGE(s, t, M*G.V(), C*G.V());
G.insert(z);
z->addflowto(t, z->cap());
dfsR(z);
for (valid = 1; ; valid++ )
{
phi[t] = z->costRto(s); mark[t] = valid;
for (int v = 0; v < G.V(); v++)
if (v != t) phi[v] = phiR(v);
Edge *x = besteligible();
if (costR(x, x->v()) == 0) break;
update(augment(x), x);
}
G.remove(z); delete z;
}
-----
int old = 0;
for (valid = 1; valid != old; )
{
old = valid;
for (int v = 0; v < G.V(); v++)
{
typename Graph::adjIterator A(G, v);
for (Edge* e = A.beg(); !A.end(); e = A.nxt())
if (e->capRto(e->other(v)) > 0)
if (e->capRto(v) == 0)
{ update(augment(e), e); valid++; }
}
}