簡體   English   中英

圖重路由算法黑客排名

[英]graph rerouting algorithm hacker rank

我試圖解決黑客級別的重新路由問題。 比賽結束后,我在這里發帖尋求幫助。

https://www.hackerrank.com/contests/hack-the-interview-v-asia-pacific/challenges/rerouting

我嘗試使用強連接組件解決問題,但測試用例失敗。 我可以理解我們必須刪除循環。 但我堅持如何解決問題。 以下是我寫的解決方案。 我正在尋找如何前進的指導,以便我可以根據我在這里犯的錯誤應用我的知識未來。 感謝您的時間和幫助

int getMinConnectionChange(vector<int> connection) {
    
    // Idea: Get number of strongly connected components.
    int numberOfVertices = connection.size();
    for(int idx = 0; idx < numberOfVertices; idx++) {
        cout << idx+1 <<":"<< connection[idx] << endl;
    }
    stack<int> stkVertices; 
    map<int, bool> mpVertexVisited; //is vertex visited.think this as a chalk mark for nodes visited.
    
    
    int numOFSCCs = 0;
    int currTime = 1;
    for (int vertexId = 0; vertexId < numberOfVertices; vertexId++) {
        // check if node is already visited.
        if (mpVertexVisited.find(vertexId+1) == mpVertexVisited.end()) {
            numOFSCCs++;
            mpVertexVisited.insert(make_pair(vertexId+1, true));
            stkVertices.push(vertexId+1);
            currTime++;

            while (!stkVertices.empty()) {
                int iCurrentVertex = stkVertices.top();
                stkVertices.pop(); 
                // get adjacent vertices. In this excercise we have only one neighbour. i.e., edge
                int neighbourVertexId = connection[iCurrentVertex-1];
                // if vertex is already visisted, don't insert in to stack.
                if (mpVertexVisited.find(neighbourVertexId) != mpVertexVisited.end()) {
                    continue;
                }
                mpVertexVisited.insert(make_pair(neighbourVertexId, true));
                stkVertices.push(neighbourVertexId);            
            } // while loop
        } // if condition m_mapVrtxTimes.find(*itr) == m_mapVrtxTimes.end()
    } // for loop of vertices
    return numOFSCCs - 1;

}

這是我剛剛解決的問題,並想分享解決方案。

這個問題可以用 union-find 來解決。

兩個主要觀察:

  1. 必須改變的邊number of components - 1 (不一定是強連接的) Thus, union-find is handy here for finding the number of components
  2. 第二個觀察是某些組件沒有終止節點,考慮1<->2 ,換句話說,存在一個循環。 如果某個節點沒有出邊,我們可以檢測是否存在終止節點。

如果所有組件都有一個循環,這意味着我們需要更改每個組件而不是a number of components - 1 這是為了使圖形具有終止點。

代碼:

struct UF {
    vector<int> p, rank, size;
    int cnt;
    UF(int N) {
        p = rank = size = vector<int>(N, 1);
        for (int i = 0; i < N; i++) p[i] = i;
        cnt = N;
    }
    int find(int i) {
        return p[i] == i ? i : p[i] = find(p[i]);
    }
    bool connected(int i, int j) {
        return find(i) == find(j);
    }
    void join(int i, int j) {
        if (connected(i, j)) return;
        int x = find(i), y = find(j);
        cnt--;
        if (rank[x] > rank[y]) {
            p[y] = x;
            size[x] += size[y];
        } else {
            p[x] = y;
            size[y] += size[x];
            if (rank[x] == rank[y]) rank[y]++;
        }
    }
};

int getMinConnectionChange(vector<int> connection) {
    int nonCycle = 0;
    int n = connection.size();
    UF uf(n);
    for(int i=0;i<n;i++) {
        int to = connection[i] - 1;
        if(to == i) nonCycle++;
        else uf.join(i, to);
    }
    int components = uf.cnt;
    int countCycle = uf.cnt - nonCycle;
    int res = components - 1;
    if(countCycle == components) res++; // all components have cycle
    return res;
}

TL;DR:您可以將其視為尋找最小跨度樹狀結構問題

更准確地說,為每個服務器添加一個節點,另一個稱為“Terminate”。 制作一個完整的圖(每個節點都鏈接到其他每個節點)並將與您的輸入對應的邊設置為成本 0,其他邊設置為 1。

您可以使用例如Edmond 的算法來解決這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM