00001 //---------------------------------------------------------------------------- 00002 /** @file GraphUtils.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "BoardUtils.hpp" 00007 #include "BitsetIterator.hpp" 00008 #include "GraphUtils.hpp" 00009 00010 using namespace benzene; 00011 00012 //---------------------------------------------------------------------------- 00013 00014 void GraphUtils::ComputeDigraph(const Groups& groups, HexColor color, 00015 PointToBitset& nbs) 00016 { 00017 nbs.clear(); 00018 00019 // Copy adjacent nbs 00020 HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(color); 00021 for (GroupIterator g(groups, not_other); g; ++g) 00022 nbs[g->Captain()] = groups.Nbs(*g, EMPTY); 00023 00024 // Go through groups of color 00025 for (GroupIterator g(groups, EMPTY); g; ++g) 00026 { 00027 for (BitsetIterator nb(groups.Nbs(*g, color)); nb; ++nb) 00028 { 00029 nbs[g->Captain()] |= nbs[groups.CaptainOf(*nb)]; 00030 nbs[g->Captain()].reset(g->Captain()); 00031 } 00032 } 00033 } 00034 00035 //---------------------------------------------------------------------------- 00036 00037 bitset_t GraphUtils::BFS(HexPoint p, PointToBitset& group_nbs, 00038 bitset_t stopSet, int* distFromStart, 00039 int* numShortestPathsThru) 00040 { 00041 // Initialize distances from BFS starting point and number of shortest 00042 // paths through a location (if these values are desired). 00043 bool recordDistance = (distFromStart != NULL); 00044 bool computeFrequency = (numShortestPathsThru != NULL); 00045 HexAssert(recordDistance || !computeFrequency); 00046 00047 if (recordDistance) { 00048 for (int i=0; i<BITSETSIZE; i++) 00049 distFromStart[i] = NOT_REACHED; 00050 distFromStart[p] = 0; 00051 00052 if (computeFrequency) { 00053 for (int i=0; i<BITSETSIZE; i++) 00054 numShortestPathsThru[i] = 0; 00055 numShortestPathsThru[p] = 1; 00056 } 00057 } 00058 00059 // Initialize queue to starting point and alter stop set to exclude start. 00060 bitset_t visited; 00061 std::queue<HexPoint> q; 00062 q.push(p); 00063 visited.set(p); 00064 bitset_t stop = stopSet; 00065 stop.reset(p); 00066 00067 // Continue BFS until all reachable cells have been visited. 00068 while (!q.empty()) { 00069 // Get next cell on queue 00070 HexPoint curCell = q.front(); 00071 q.pop(); 00072 00073 // Do not add this cell's neighbours if it is marked as a stop cell. 00074 if (stop.test(curCell)) continue; 00075 00076 // Compute current cell's neighbours, and update number of paths this 00077 // cell's neighbours are on. 00078 bitset_t nbs = group_nbs[curCell]; 00079 if (computeFrequency) { 00080 for (int i=0; i<BITSETSIZE; i++) { 00081 if (!nbs.test(i)) continue; 00082 if (distFromStart[i] == NOT_REACHED || 00083 distFromStart[i] > distFromStart[curCell]) 00084 numShortestPathsThru[i] += numShortestPathsThru[curCell]; 00085 } 00086 } 00087 00088 // Add previously-unvisited neighbours to queue and mark as visited. 00089 nbs = nbs - visited; 00090 visited |= nbs; 00091 for (BitsetIterator i(nbs); i; ++i) { 00092 q.push(*i); 00093 if (recordDistance) 00094 distFromStart[*i] = distFromStart[curCell] + 1; 00095 } 00096 } 00097 00098 return visited; 00099 } 00100 00101 //----------------------------------------------------------------------------