This file contains the code from "Algorithms in C++, Third Edition, Part 5," by Robert Sedgewick, and is covered under the copyright and warranty notices in that book. Permission is granted for this code to be used for educational purposes in association with the text, and for other uses not covered by copyright laws, provided that the following notice is included with the code: "This code is from "Algorithms in C++, Third Edition," by Robert Sedgewick, Addison-Wesley, 2002." Commercial uses of this code require the explicit written permission of the publisher. Send your request for permission, stating clearly what code you would like to use, and in what specific way, to: aw.cse@aw.com ---------- 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 vector edges(Graph &G) { int E = 0; vector 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 void IO::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 IO { public: static void show(const Graph &); static void scanEZ(Graph &); static void scan(Graph &); }; ----- template class CC { private: // implementation-dependent code public: CC(const Graph &); int count(); bool connect(int, int); }; ----- #include #include #include "GRAPH.cc" #include "IO.cc" #include "CC.cc" main(int argc, char *argv[]) { int V = atoi(argv[1]); GRAPH G(V); IO::scan(G); if (V < 20) IO::show(G); cout << G.E() << " edges "; CC Gcc(G); cout << Gcc.count() << " components" << endl; } ----- class DenseGRAPH { int Vcnt, Ecnt; bool digraph; vector > 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 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 DEGREE { const Graph &G; vector 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 void IO::scan(Graph &G) { string v, w; ST st; while (cin >> v >> w) G.insert(Edge(st.index(v), st.index(w))); } ----- #include 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 sPATH { const Graph &G; vector 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 ePATH { Graph G; int v, w; bool found; STACK S; int tour(int v); public: ePATH(const Graph &G, int v, int w) : G(G), v(v), w(w) { DEGREE 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 int ePATH::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 void ePATH::show() { if (!found) return; while (tour(v) == v && !S.empty()) { v = S.pop(); cout << "-" << v; } cout << endl; } ---------- CHAPTER 18. Graph Search ----- #include template class cDFS { int cnt; const Graph &G; vector 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 SEARCH { protected: const Graph &G; int cnt; vector 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 DFS : public SEARCH { vector 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(G), st(G.V(), -1) { search(); } int ST(int v) const { return st[v]; } }; ----- template class CC { const Graph &G; int ccnt; vector 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 EULER : public SEARCH { 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(G) { search(); } }; ----- template class BI { const Graph &G; bool OK; vector 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 EC : public SEARCH { int bcnt; vector 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(G), bcnt(0), low(G.V(), -1) { search(); } int count() const { return bcnt+1; } }; ----- #include "QUEUE.cc" template class BFS : public SEARCH { vector st; void searchC(Edge e) { QUEUE 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(G), st(G.V(), -1) { search(); } int ST(int v) const { return st[v]; } }; ----- void searchC(Edge e) { QUEUE 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 PFS : public SEARCH { vector st; void searchC(Edge e) { GQ 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(G), st(G.V(), -1) { search(); } int ST(int v) const { return st[v]; } }; ----- template class GQ { private: vector 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 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 DFS { const Graph &G; int depth, cnt, cntP; vector 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 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 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 dagTS { const Dag &D; int cnt, tcnt; vector 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 dagTS { const Dag &D; vector in, ts, tsI; public: dagTS(const Dag &D) : D(D), in(D.V(), 0), ts(D.V(), -1), tsI(D.V(), -1) { QUEUE 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 dagTC { tcDag T; const Dag &D; int cnt; vector 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 SC { const Graph &G; int cnt, scnt; vector 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 SC { const Graph &G; STACK S; int cnt, scnt; vector 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 TC { const Graph &G; DenseGRAPH *K; dagTC *Ktc; SC *Gsc; public: TC(const Graph &G) : G(G) { Gsc = new SC(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(*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 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 vector edges(const Graph &G) { int E = 0; vector 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 DenseGRAPH { int Vcnt, Ecnt; bool digraph; vector > 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 DenseGRAPH::adjIterator { const DenseGRAPH &G; int i, v; public: adjIterator(const DenseGRAPH &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 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 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 MST { const Graph &G; vector wt; vector 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 MST { const Graph &G; vector wt; vector fr, mst; void pfs(int s) { PQi 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 MST { const Graph &G; vector 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(G); sort(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 MST { const Graph &G; vector a, b, mst; UF uf; public: MST(const Graph &G): G(G), uf(G.V()), mst(G.V()+1) { a = edges(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 PQi { int d, N; vector pq, qp; const vector &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 &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 SPT { const Graph &G; vector wt; vector spt; public: SPT(const Graph &G, int s) : G(G), spt(G.V()), wt(G.V(), G.V()) { PQi 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 SPall { public: SPall(const Graph &); Edge *path(int, int) const; Edge *pathR(int, int) const; double dist(int, int) const; }; ----- template double diameter(Graph &G) { int vmax = 0, wmax = 0; allSP 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 allSP { const Graph &G; vector< SPT *> A; public: allSP(const Graph &G) : G(G), A(G.V()) { for (int s = 0; s < G.V(); s++) A[s] = new SPT(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 allSP { const Graph &G; vector > p; vector > 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 LPTdag { const Graph &G; vector wt; vector lpt; public: LPTdag(const Graph &G) : G(G), lpt(G.V()), wt(G.V(), 0) { int j, w; dagTS 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 allSPdag { const Graph &G; vector > p; vector > 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 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 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 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 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 MAXFLOW { const Graph &G; int s, t; vector wt; vector 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 bool MAXFLOW::pfs() { PQi 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 MAXFLOW { const Graph &G; int s, t; vector 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 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 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(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 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, EDGE>(G, 2*N, 2*N+1); for (int i = 0; i < N; i++) { GRAPH::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 MINCOST { const Graph &G; int s, t; vector wt; vector 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(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 MINCOST { const Graph &G; int s, t; int valid; vector st; vector 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++; } } }