Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/mst/check.cpp
00001 // usage:
00002 //      check
00003 //
00004 // Check reads two graphs from stdin, and checks to see
00005 // if the second is a minimum spanning tree of the first.
00006 // It prints a message for each discrepancy that it finds.
00007 //
00008 // This program is not bullet-proof. Caveat emptor.
00009 
00010 #include "stdinc.h"
00011 #include "List.h"
00012 #include "ClistSet.h"
00013 #include "Wgraph.h"
00014 #include "Partition.h"
00015 
00016 using namespace grafalgo;
00017 
00018 void check(Wgraph&, Wgraph&);
00019 void verify(Wgraph&, Wgraph&);
00020 void rverify(Wgraph&, Wgraph&, vertex, vertex, vertex*,
00021              ClistSet&, vertex*, int*);
00022 int max_wt(vertex, vertex, vertex*, vertex*);
00023 void nca(Wgraph&, Wgraph&, vertex*, ClistSet&);
00024 void nca_search(Wgraph&, Wgraph&, vertex, vertex, vertex*,
00025         ClistSet&, Partition&, vertex*, int*);
00026 
00027 int main() {
00028         Wgraph wg; cin >> wg;
00029         Wgraph mstree; cin >> mstree;
00030         check(wg,mstree);
00031 }
00032 
00033 // Verify that mstree is a minimum spanning tree of wg.
00034 void check(Wgraph& wg, Wgraph& mstree) {
00035         vertex u,v; edge e, f;
00036 
00037         // check that mstree is a subgraph of wg
00038         if (mstree.n() != wg.n() || mstree.m() != mstree.n()-1) {
00039                 Util::fatal("check: size error, aborting\n");
00040         }
00041         vertex* edgeTo = new vertex[mstree.n()+1];
00042         for (u = 1; u <= wg.n(); u++) edgeTo[u] = 0;
00043         for (u = 1; u <= wg.n(); u++) {
00044                 for (e = wg.firstAt(u); e != 0; e = wg.nextAt(u,e))
00045                         edgeTo[wg.mate(u,e)] = e;
00046                 for (f = mstree.firstAt(u); f != 0; f = mstree.nextAt(u,f)) {
00047                         v = mstree.mate(u,f);
00048                         e = edgeTo[v];
00049                         if (e == 0 || mstree.weight(f) != wg.weight(e)) {
00050                                 string s;
00051                                 cout << "check: edge " << f << "="
00052                                      << mstree.edge2string(f,s)
00053                                      << " is not in wg\n";
00054                         }
00055                 }
00056                 for (e = wg.firstAt(u); e != 0; e = wg.nextAt(u,e))
00057                         edgeTo[wg.mate(u,e)] = 0;
00058         }
00059 
00060         // check that mstree reaches all the vertices
00061         int* mark = new int[mstree.n()+1]; int marked;
00062         for (u = 1; u <= mstree.n(); u++) mark[u] = 0;
00063         mark[1] = 1; marked = 1;
00064         List q(wg.n()); q.addLast(1);
00065         while (!q.empty()) {
00066                 u = q.first(); q.removeFirst();
00067                 for (e = mstree.firstAt(u); e != 0; e = mstree.nextAt(u,e)) {
00068                         v = mstree.mate(u,e);
00069                         if (mark[v] == 0) {
00070                                 q.addLast(v); mark[v] = 1; marked++;
00071                         }
00072                 }
00073         }
00074         if (marked != mstree.n()) {
00075                 printf("check: mstree does not reach all vertices\n");
00076                 return;
00077         }
00078         // check that there is no cheaper spanning tree
00079         verify(wg,mstree);
00080 }
00081 
00082 // Verify that there is no cheaper spanning tree than mstree.
00083 void verify(Wgraph& wg, Wgraph& mstree) {
00084         // Determine nearest common ancestor for each edge.
00085         vertex* first_edge = new edge[wg.n()+1];
00086         ClistSet edge_sets(wg.m());
00087         nca(wg,mstree,first_edge,edge_sets);
00088 
00089         // Check paths from endpoints to nca, and compress.
00090         vertex* a = new vertex[mstree.n()+1];   // a[u] is an ancestor of u
00091         int* mw = new int[mstree.n()+1];        // mw[u] is max edge wt
00092                                                 // between u, a[u]
00093         rverify(wg,mstree,1,1,first_edge,edge_sets,a,mw);
00094 }
00095 
00096 // Recursively verify the subtree rooted at u with parent pu.
00097 void rverify(Wgraph& wg, Wgraph& mstree, vertex u, vertex pu,
00098             vertex first_edge[], ClistSet& edge_sets, vertex a[], int mw[]) {
00099         vertex v; edge e; int m;
00100         for (e = mstree.firstAt(u); e != 0; e = mstree.nextAt(u,e)) {
00101                 v = mstree.mate(u,e);
00102                 if (v == pu) continue;
00103                 a[v] = u; mw[v] = mstree.weight(e);
00104                 rverify(wg,mstree,v,u,first_edge,edge_sets,a,mw);
00105         }
00106         e = first_edge[u];
00107         if (e == 0) return;
00108         while (1) {
00109                 m = max( max_wt(wg.left(e),u,a,mw),
00110                          max_wt(wg.right(e),u,a,mw) );
00111                 if (m > wg.weight(e)) {
00112                         string s;
00113                         cout << "mst violation: edge " << e << "="
00114                              << wg.edge2string(e,s) << " in wg\n";
00115                 }
00116                 e = edge_sets.suc(e);
00117                 if (e == first_edge[u]) break;
00118         }
00119 }
00120 
00121 // Return the maximum weight of edges on path from u to v,
00122 // defined by the ancestor pointers in a. Compress a & mw as a
00123 // side effect.
00124 int max_wt(vertex u, vertex v, vertex a[], int mw[]) {
00125         if (u == v) return 0;
00126         int m = max(mw[u],max_wt(a[u],v,a,mw));
00127         a[u] = v; mw[u] = m;
00128         return m;
00129 }
00130                 
00131 // Compute the nearest common ancestors in mstree of edges in wg.
00132 // On return edge_sets contains a collection of lists, with two edges
00133 // appearing on the same list if they have the same nearest common ancestor.
00134 // On return, first_edge[u] is an edge for which u is the nearest common
00135 // ancestor, or null if there is no such edge.
00136 void nca(Wgraph& wg, Wgraph& mstree, vertex *first_edge, ClistSet& edge_sets) {
00137         Partition npap(wg.n());
00138         vertex *npa = new vertex[wg.n()+1];
00139         int *mark = new int[wg.m()+1];
00140 
00141         for (edge e = wg.first(); e != 0; e = wg.next(e)) mark[e] = 0;
00142         for (vertex u = 1; u <= wg.n(); u++) {
00143                 first_edge[u] = 0; npa[u] = u;
00144         }
00145         nca_search(wg,mstree,1,1,first_edge,edge_sets,npap,npa,mark);
00146 }
00147 
00148 void nca_search(Wgraph& wg, Wgraph& mstree, vertex u, vertex pu,
00149                 vertex first_edge[],
00150         ClistSet& edge_sets, Partition& npap, vertex npa[], int mark[]) {
00151         vertex v, w; edge e;
00152 
00153         for (e = mstree.firstAt(u); e != 0; e = mstree.nextAt(u,e)) {
00154                 v = mstree.mate(u,e);
00155                 if (v == pu) continue;
00156                 nca_search(wg,mstree,v,u,first_edge,edge_sets,npap,npa,mark);
00157                 npap.link(npap.find(u),npap.find(v));
00158                 npa[npap.find(u)] = u;
00159         }
00160         for (e = wg.firstAt(u); e != 0; e = wg.nextAt(u,e)) {
00161                 v = wg.mate(u,e);
00162                 if (! mark[e]) mark[e] = 1;
00163                 else {
00164                         w = npa[npap.find(v)];
00165                         edge_sets.join(e,first_edge[w]);
00166                         first_edge[w] = e;
00167                 }
00168         }
00169 }
00170                 
 All Classes Files Functions Variables Typedefs Friends