Grafalgo
Library of useful data structures and algorithms
|
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