2017-09-01 96 views
0

我知道這個問題已經存在,但答案並不能真正解決我的問題,因爲我似乎已經實施了它,但它仍然超時。HackerRank上的道路和圖書館(DFS)超時

HackerRank上的任務是here

主要思想是在圖表中找到「連通的組件」(即相互連接的節點組)。具體來說,統計有多少個節點,以及每個節點有多少個節點。我爲此使用了一個簡單的數組:connectedComponents[index] = numberOfNodesForAComponentAtIndex

問題是我的解決方案超時大輸入,但對於較小的輸入會產生正確的結果。

我想了解一些幫助,瞭解我的代碼的哪一部分可以變得更快。

function calculateCost(n, m, cLib, cRoad, roads) { 
    // cost of road >= cost of library? 
    if (cRoad >= cLib) { 
     // build a library in each city 
     return n * cLib; 
    } 

    // cost of road < cost of library? 
    // find connected components: build a library in only 1, and connect all others with roads 

    // infos needed: 
    // 1) how many connected components 
    // 2) how many cities in each connected component 

    // array of numbers : each number represents the number of cities in connected component at index 
    var connectedComponents = calculateConnectedComponents(n, m, roads); 

    var cost = 0; 

    for (var i = 0; i < connectedComponents.length; i++) { 
     var cc = connectedComponents[i]; 
     cost += cLib + (cc - 1) * cRoad; 
    } 

    return cost; 
} 


function calculateConnectedComponents(n, m, roads) { 
    // array of numbers : each number represents the number of cities in connected component at index 
    var connectedComponents = []; 

    // initialize all cities to not visited 
    var notExpanded = new Set(); 
    var cities = []; 

    for (var i = 1; i <= n; i++) { 
     notExpanded.add(i); 
     cities[i-1] = i; 
    } 

    var expansions = calculateExpansions(roads); 

    while (notExpanded.size > 0) { 
     // DFS 
     var stack = []; 

     // move on to the next city 
     var start = getNextCity(cities); 
     stack.push(start); 


     // mark visited 
     notExpanded.delete(start); 
     cities[start-1] = -1; 

     // calculate connected component 
     var cc = 0; 
     while (stack.length > 0) { 
      process.stdout.write("STACK: " + stack.toString() + "\n"); 
      var city = stack.pop(); 

      process.stdout.write("City: " + city.toString() + "\n"); 

      cC++; 

      // mark visited 
      cities[city-1] = -1; 

      var expanded = expand(city, expansions); 
      process.stdout.write("EXP: " + expanded.toString() + "\n\n"); 

      for (var i = 0; i < expanded.length; i++) { 
       if (notExpanded.has(expanded[i])) { 
        notExpanded.delete(expanded[i]); 
        stack.push(expanded[i]); 
       }   
      } 
     } 

     connectedComponents.push(cc); 
    } 

    return connectedComponents; 
} 

function calculateExpansions(roads) { 
    var expansions = {}; 

    for (var i = 0; i < roads.length; i++) { 
     var road = roads[i]; 

     if (!(road.c1 in expansions)) { 
      var exp = []; 
      exp.push(road.c2); 
      expansions[road.c1] = exp; 
     } else { 
      expansions[road.c1].push(road.c2); 
     } 

     if (!(road.c2 in expansions)) { 
      var exp = []; 
      exp.push(road.c1); 
      expansions[road.c2] = exp; 
     } else { 
      expansions[road.c2].push(road.c1); 
     } 
    } 

    return expansions; 
} 

function expand(city, expansions) {  
    if (expansions[city]) { 
     return expansions[city]; 
    } else { 
     return []; 
    } 
} 


function getNextCity(cities) { 
    for (var i = 0; i < cities.length; i ++) { 
     if (cities[i] !== -1) { 
      return cities[i]; 
     } 
    } 

    // error, should not happen 
    return -1; 
} 

function main() { 
    var q = parseInt(readLine()); 

    var costs = []; 


    for(var a0 = 0; a0 < q; a0++){ 

     var n_temp = readLine().split(' '); 
     var n = parseInt(n_temp[0]); 
     var m = parseInt(n_temp[1]); 
     var x = parseInt(n_temp[2]); 
     var y = parseInt(n_temp[3]); 

     var roads = []; 

     for(var a1 = 0; a1 < m; a1++){ 
      var city_1_temp = readLine().split(' '); 
      var city_1 = parseInt(city_1_temp[0]); 
      var city_2 = parseInt(city_1_temp[1]); 

      var road = { 
       c1 : city_1, 
       c2 : city_2 
      }; 

      roads.push(road); 
     } 

     // n : number of cities 
     // m : number of roads 
     // x : cost of the library 
     // y : cost of the road 
     // roads: road connections 
     costs.push(calculateCost(n, m, x, y, roads)); 
    } 

    process.stdout.write(costs.join("\n").toString()); 
} 

回答

1

看起來可能很慢的一件事是getNextCity。

如果圖中沒有道路,那麼你會調用getNextCity n次,每次都是O(n)運算,所以總的來說複雜度是O(n^2)。

改進此方法的一種方法是僅從最後找到的城市進行搜索,而不是從每次從0開始搜索。這會將這部分的複雜度從O(n^2)降低到O(n),因爲每個城市只會被測試一次。