[英]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 來解決。
兩個主要觀察:
number of components - 1
(不一定是強連接的) Thus, union-find is handy here for finding the number of components
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.