@@ -195,6 +195,9 @@ public Set<String> independentDominatingSet() {
195195 * subgraph is connected. Uses a BFS-tree approach starting from the
196196 * highest-degree vertex.
197197 *
198+ * <p>Maintains a frontier set of vertices adjacent to the current CDS
199+ * so the connectivity check is O(1) instead of O(|CDS|) per candidate.</p>
200+ *
198201 * @return an unmodifiable connected dominating set, or empty if graph
199202 * is disconnected or empty
200203 */
@@ -213,23 +216,21 @@ public Set<String> connectedDominatingSet() {
213216
214217 Set <String > cds = new LinkedHashSet <String >();
215218 Set <String > dominated = new HashSet <String >();
219+ // Frontier: non-CDS vertices adjacent to at least one CDS member
220+ Set <String > frontier = new HashSet <String >();
221+
216222 cds .add (start );
217223 dominated .add (start );
218224 dominated .addAll (adj .get (start ));
225+ for (String n : adj .get (start )) {
226+ if (!cds .contains (n )) frontier .add (n );
227+ }
219228
220229 // Grow the CDS by adding connector vertices
221230 while (dominated .size () < adj .size ()) {
222231 String best = null ;
223232 int bestScore = -1 ;
224- for (String v : adj .keySet ()) {
225- if (cds .contains (v )) continue ;
226- // Must be adjacent to at least one CDS member (connectivity)
227- boolean connects = false ;
228- for (String m : cds ) {
229- if (adj .get (v ).contains (m )) { connects = true ; break ; }
230- }
231- if (!connects ) continue ;
232-
233+ for (String v : frontier ) {
233234 int score = 0 ;
234235 for (String n : adj .get (v )) {
235236 if (!dominated .contains (n )) score ++;
@@ -242,8 +243,12 @@ public Set<String> connectedDominatingSet() {
242243 }
243244 if (best == null ) break ; // disconnected graph
244245 cds .add (best );
246+ frontier .remove (best );
245247 dominated .add (best );
246- dominated .addAll (adj .get (best ));
248+ for (String n : adj .get (best )) {
249+ dominated .add (n );
250+ if (!cds .contains (n )) frontier .add (n );
251+ }
247252 }
248253
249254 if (dominated .size () < adj .size ()) return Collections .emptySet ();
@@ -311,23 +316,22 @@ public Set<String> kDominatingSet(int k) {
311316 /**
312317 * Checks whether the given set is a valid dominating set.
313318 *
319+ * <p>Instead of checking every non-member vertex against every candidate
320+ * member (O(V·D)), we build the dominated set in O(D·avg_degree) by
321+ * collecting the closed neighborhoods of all candidates, then verify
322+ * full coverage in O(1).</p>
323+ *
314324 * @param candidate the set to verify
315325 * @return true if every vertex is in the set or adjacent to a member
316326 */
317327 public boolean isDominatingSet (Set <String > candidate ) {
318328 if (candidate == null ) return false ;
319- for (String v : adj .keySet ()) {
320- if (candidate .contains (v )) continue ;
321- boolean covered = false ;
322- for (String m : candidate ) {
323- if (adj .containsKey (v ) && adj .get (v ).contains (m )) {
324- covered = true ;
325- break ;
326- }
327- }
328- if (!covered ) return false ;
329+ Set <String > dominated = new HashSet <String >(candidate );
330+ for (String m : candidate ) {
331+ Set <String > neighbors = adj .get (m );
332+ if (neighbors != null ) dominated .addAll (neighbors );
329333 }
330- return true ;
334+ return dominated . size () >= adj . size () ;
331335 }
332336
333337 /**
@@ -386,20 +390,30 @@ public int dominationUpperBound() {
386390 /**
387391 * For a given dominating set, returns how many members dominate each vertex.
388392 *
393+ * <p>Instead of iterating all dominators for each vertex (O(V·D)),
394+ * iterates each dominator's neighborhood once (O(D·avg_degree)),
395+ * incrementing coverage counters via the adjacency structure.</p>
396+ *
389397 * @param dominatingSet the dominating set
390398 * @return map from vertex to number of covering dominators
391399 */
392400 public Map <String , Integer > coverageMap (Set <String > dominatingSet ) {
393401 Map <String , Integer > coverage = new LinkedHashMap <String , Integer >();
394402 for (String v : adj .keySet ()) {
395- int count = 0 ;
396- if (dominatingSet .contains (v )) count ++; // self-domination
397- for (String m : dominatingSet ) {
398- if (!m .equals (v ) && adj .get (v ) != null && adj .get (v ).contains (m )) {
399- count ++;
403+ coverage .put (v , 0 );
404+ }
405+ for (String m : dominatingSet ) {
406+ // Self-domination
407+ Integer selfCount = coverage .get (m );
408+ if (selfCount != null ) coverage .put (m , selfCount + 1 );
409+ // Neighbor domination
410+ Set <String > neighbors = adj .get (m );
411+ if (neighbors != null ) {
412+ for (String n : neighbors ) {
413+ Integer count = coverage .get (n );
414+ if (count != null ) coverage .put (n , count + 1 );
400415 }
401416 }
402- coverage .put (v , count );
403417 }
404418 return coverage ;
405419 }
0 commit comments