Java程式:查詢圖中的良好反饋頂點集
該Java程式旨在在一個圖中找到一個良好的反饋頂點集。反饋頂點集是圖中的一組頂點,移除這些頂點及其關聯邊後,得到的圖是無環的。該程式使用一種演算法方法來識別一個小的反饋頂點集,該集合保留了圖的基本屬性。透過迭代選擇度數高的頂點並移除其關聯邊,該程式找到一個近似解。這使得能夠高效地識別圖中導致迴圈的關鍵頂點。找到的反饋頂點集可用於各種應用,例如網路分析和最佳化。
使用的方法
近似演算法
暴力法
近似演算法
在Java程式查詢圖中良好反饋頂點集的背景下,近似演算法是一種保證在最優解的某個因子內的解的方法。該演算法透過迭代選擇度數最高的頂點並將其及其關聯邊移除來開始。然而,與貪婪演算法不同,這種方法還會考慮移除度數較低的頂點,如果這樣做有助於打破迴圈。透過迭代移除頂點,該演算法最終形成一個無環圖,而選擇的頂點構成反饋頂點集。考慮到計算效率,近似演算法提供了一個相當好的解。
演算法
初始化一個空集 S 來儲存選擇的頂點。
當 G 包含邊時,
a. 在 G 中找到度數最高的頂點 v。
b. 將 v 新增到 S。
c. 從 G 中移除 v 及其關聯邊。
d. 重複步驟 a-c,直到 G 變成無邊圖。
對於 G 中每個剩餘頂點 u
a. 如果 u 與 S 中的任何頂點相鄰,則從 G 中移除 u。
返回 S 作為近似的反饋頂點集。
示例
#include <iostream> #include <vector> #include <set> #include <algorithm> // Include the algorithm header for sort function using namespace std; // Function to find a good feedback vertex set in a graph set<int> findFeedbackVertexSet(vector<vector<int>>& graph) { int n = graph.size(); vector<pair<int, int>> degrees; // Calculate the degrees of each vertex for (int i = 0; i < n; ++i) { degrees.push_back({graph[i].size(), i}); } // Sort the vertices in descending order of degrees sort(degrees.rbegin(), degrees.rend()); set<int> feedbackVertexSet; // Greedily select vertices with the highest degree for (int i = 0; i < n; ++i) { int vertex = degrees[i].second; // Check if adding this vertex forms a cycle bool formsCycle = false; for (int neighbor : graph[vertex]) { if (feedbackVertexSet.count(neighbor) > 0) { formsCycle = true; break; } } // If adding this vertex does not form a cycle, add it to the feedback vertex set if (!formsCycle) { feedbackVertexSet.insert(vertex); } } return feedbackVertexSet; } // Test the function int main() { // Create a sample graph vector<vector<int>> graph = { {1, 2, 3}, {0, 3}, {0, 3}, {0, 1, 2} }; // Find a good feedback vertex set set<int> feedbackSet = findFeedbackVertexSet(graph); // Print the vertices in the feedback vertex set cout << "Feedback Vertex Set: "; for (int vertex : feedbackSet) { cout << vertex << " "; } cout << endl; return 0; }
輸出
Feedback Vertex Set: 3
暴力法
在查詢圖中良好反饋頂點集的背景下,暴力法包括徹底檢查所有可能的頂點組合,以確定打破所有迴圈的最小集合。它有效地生成所有頂點子集,並檢查移除這些頂點是否使圖無環。這種方法保證找到最優解,但由於其指數時間複雜度,對於大型圖來說變得不可行。暴力法包括遍歷所有可能的頂點組合,從圖中移除它們,並檢查無環性,直到找到最小反饋頂點集。
演算法
初始化一個變數來儲存反饋頂點集的最小大小。
生成圖中所有可能的頂點子集。
對於每個子集,從圖中移除頂點,並檢查結果圖是否無環。
如果圖是無環的,則計算當前子集的大小。
如果當前子集的大小小於最小大小,則更新最小大小。
對所有生成的子集重複步驟 3-5。
返回反饋頂點集的最小大小。
示例
#include <iostream> #include <vector> #include <set> using namespace std; // Function to check if the given vertices form a feedback vertex set bool isFeedbackVertexSet(const vector<vector<int>>& graph, const set<int>& vertices) { // Check if each vertex in the set breaks a cycle for (int vertex : vertices) { for (int neighbor : graph[vertex]) { if (vertices.find(neighbor) == vertices.end()) { return false; // A cycle exists, so not a feedback vertex set } } } return true; // No cycles found, so it's a feedback vertex set } // Recursive function to find all possible feedback vertex sets void findAllFeedbackVertexSets(const vector<vector<int>>& graph, set<int>& currentSet, int vertex, vector<set<int>>& allSets) { // Base case: reached the end of the graph if (vertex == graph.size()) { if (isFeedbackVertexSet(graph, currentSet)) { allSets.push_back(currentSet); } return; } // Recursive case: include current vertex or exclude it currentSet.insert(vertex); findAllFeedbackVertexSets(graph, currentSet, vertex + 1, allSets); currentSet.erase(vertex); findAllFeedbackVertexSets(graph, currentSet, vertex + 1, allSets); } // Function to find a good feedback vertex set in the graph set<int> findGoodFeedbackVertexSet(const vector<vector<int>>& graph) { vector<set<int>> allSets; set<int> currentSet; // Find all possible feedback vertex sets findAllFeedbackVertexSets(graph, currentSet, 0, allSets); // Find the smallest feedback vertex set set<int> smallestSet; size_t smallestSize = graph.size() + 1; for (const set<int>& vertices : allSets) { if (vertices.size() < smallestSize) { smallestSize = vertices.size(); smallestSet = vertices; } } return smallestSet; } int main() { // Define the graph as an adjacency list vector<vector<int>> graph = { {1, 2}, {0, 2, 3}, {0, 1, 3, 4}, {1, 2, 4}, {2, 3} }; // Find a good feedback vertex set in the graph set<int> feedbackVertexSet = findGoodFeedbackVertexSet(graph); // Print the result cout << "Feedback Vertex Set: "; if (!feedbackVertexSet.empty()) { for (int vertex : feedbackVertexSet) { cout << vertex << " "; } } else { cout << "No feedback vertex set found."; } cout << endl; return 0; }
輸出
Feedback Vertex Set: No feedback vertex set found.
結論
本文闡述了在確定是否可以分配滿足給定約束的值的上下文中,約束滿足和約束傳播的概念。它概述了所涉及的演算法方法,並提供了C++程式碼示例。本文闡述了在確定是否可以分配滿足給定約束的值的上下文中,約束滿足和約束傳播的概念。它概述了所涉及的演算法方法,並提供了C++程式碼示例。
約束滿足包括確定是否可以將值分配給變數以滿足給定的約束,而約束傳播則迭代地應用規則以基於關係減少可能的值。本文說明了如何使用這些程式來解決滿足變數之間關係的問題,強調了有效搜尋空間探索和消除衝突分配的重要性。