void findShortestPaths(string node, int indx, unordered_map<string, unordered_set<string>>& parents, vector<string>& solution, vector<vector<string>>& result) { if(parents[node].find(node) != parents[node].end()) { assert(indx == 0); solution[indx] = node; result.push_back(solution); return; } solution[indx] = node; for(auto parentIter = parents[node].begin(); parentIter != parents[node].end(); ++parentIter) { findShortestPaths(*parentIter, indx - 1, parents, solution, result); } }
vector<vector<string>> findLadders(string beginWord, string endWord, unordered_set<string> &wordList) { queue<string> Q; unordered_map<string, bool> visited; unordered_map<string, int> level; unordered_map<string, unordered_set<string>> parents; Q.push(beginWord); level[beginWord] = 1; parents[beginWord].insert(beginWord); int depth = INT_MAX; while(!Q.empty()) { string node = Q.front(); visited[node] = true; Q.pop(); if(level[node] > depth) { break; } if(level[node] == depth and node != endWord) { continue; } if(isNextState(node, endWord)) { level[endWord] = level[node] + 1; parents[endWord].insert(node); Q.push(endWord); depth = level[endWord]; continue; } vector<string> neighs; findAdjList(node, wordList, neighs); for(int i = 0; i < (int)neighs.size(); ++i) { string neigh = neighs[i]; if(level[neigh] > 0) { if(level[node] >= level[neigh]) { continue; } } if(!visited[neigh]) { Q.push(neigh); parents[neigh].insert(node); level[neigh] = level[node] + 1; if(neigh == endWord) { depth = level[neigh]; } } } } vector<vector<string>> result; if(depth == INT_MAX) return result; vector<string> solution(depth, ""); findShortestPaths(endWord, depth - 1, parents, solution, result); return result; }
void Search::Run(const Inputs &inputs) { for(Inputs::const_iterator ngi = inputs.begin(); ngi!=inputs.end(); ++ngi) { node_iter ni; for(ni = nodes().begin(); ni!=nodes().end(); ++ni) if(gd<Name>(*ni)==ngi->first) { StrGraph &dest = gd<SearchStage>(*ni).result; dest = *ngi->second; break; } /* if(ni==nodes().end()) throw StageNotFound(ngi->first); */ } while(1) { Node *stage = 0; // find a stage for which all prereq stages are done for(node_iter ni = nodes().begin(); ni!=nodes().end(); ++ni) { if(gd<SearchStage>(*ni).done) continue; inedge_iter ei; for(ei = (*ni)->ins().begin(); ei!=(*ni)->ins().end(); ++ei) if(!gd<SearchStage>((*ei)->tail).done) break; if(ei==(*ni)->ins().end()) { stage = *ni; break; } } if(!stage) break; SearchStage &earchage = gd<SearchStage>(stage); Search::inedge_iter ei = stage->ins().begin(); if(ei!=stage->ins().end()) switch(earchage.type) { case UnionInquiry: earchage.result = gd<SearchStage>((*ei)->tail).result; for(; ei!=stage->ins().end(); ++ei) earchage.result |= gd<SearchStage>((*ei)->tail).result; break; case IntersectionInquiry: earchage.result = gd<SearchStage>((*ei)->tail).result; for(; ei!=stage->ins().end(); ++ei) earchage.result &= gd<SearchStage>((*ei)->tail).result; break; case PatternInquiry: { if(!earchage.pattern) throw PatternNotThere(); earchage.result.clear(); queue<Match> Q; PathsFollowed followed; for(; ei!=stage->ins().end(); ++ei) { Name inputname = gd<Name>(*ei); Pattern::node_iter ni; for(ni = earchage.pattern->nodes().begin(); ni!=earchage.pattern->nodes().end(); ++ni) if(gd<Name>(*ni)==inputname) { StrGraph &input = gd<SearchStage>((*ei)->tail).result; for(StrGraph::node_iter inpi = input.nodes().begin(); inpi !=input.nodes().end(); ++inpi) { earchage.result.insert(*inpi); Q.push(Match(*ni,source.find(*inpi))); } break; } if(ni==earchage.pattern->nodes().end()) throw PatternStateNotFound(inputname); } runPattern(Q,followed,earchage.limit,&earchage.result); break; } case PathInquiry: { earchage.result.clear(); StrGraph *a = 0, *b = 0; for(; ei!=stage->ins().end(); ++ei) { DString inputname = gd<Name>(*ei); if(inputname=="a") a = &gd<SearchStage>((*ei)->tail).result; else if(inputname=="b") b = &gd<SearchStage>((*ei)->tail).result; } if(a&&b) if(earchage.shortest) findShortestPaths(source,*a,*b,earchage.weightattr,earchage.limit,earchage.result); else findAllPaths(source,*a,*b,earchage.goOut,earchage.goIn,earchage.firstOnly,earchage.limit,earchage.result); } } earchage.done = true; } }