1. 程式人生 > 其它 >LeetCode 1489. 找到最小生成樹裡的關鍵邊和偽關鍵邊

LeetCode 1489. 找到最小生成樹裡的關鍵邊和偽關鍵邊

技術標籤:刷題

難度:困難。
標籤:深度優先搜尋,並查集。

看了提示,需要用Kruskal演算法來計算最小生成樹,方法如下:

  1. 計算最小生成樹的權重為 m i n W e i g h t minWeight minWeight
  2. 遍歷所有邊,指定以當前邊為最小生成樹中的邊來構建最小生成樹,若構建成功且當 n o w W e i g h t = = m i n W e i g h t nowWeight == minWeight nowWeight==minWeight 時,則該邊為有效邊;否則(構建不成功,或構建成功權重變大)為無效邊。
  3. 當邊為有效邊時,繼續,進一步判斷其為關鍵邊或非關鍵邊。
  4. 將當前邊刪除用其餘邊來構建最小生成樹,若構建成功且 n o w W e i g h t = = m i n W e i g h t nowWeight == minWeight nowWeight==minWeight,則該邊為非關鍵邊;否則為關鍵邊。

正確解法:

struct Edge{
    int start, end;
    int weight;
    int index;
};

bool cmp(Edge x, Edge y){
    return x.weight < y.weight;
}

void printStructArray(vector<Edge>
struct_edges){ cout << "--------------size:-------------------" << struct_edges.size() << endl; for(int i = 0; i < struct_edges.size(); i++){ cout << "[ " << struct_edges[i].start << "," << struct_edges[i].end <<
"," << struct_edges[i].weight << "," << struct_edges[i].index << "]"; } cout << endl << endl; } class unionfindSet{ public: vector<int> parent; vector<int> rank; unionfindSet(int n):parent(vector<int> (n)), rank(vector<int> (n)){ for(int i = 0; i < n; i++){ parent[i] = i; } } int find_root(int x){ if(x != parent[x]){ parent[x] = find_root(parent[x]); } return parent[x]; } void merge(int x, int y){ int rootx = find_root(x); int rooty = find_root(y); if(rootx != rooty){ if(rank[rootx] < rank[rooty]){ swap(rootx, rooty); } parent[rooty] = rootx; if(rank[rootx] == rank[rooty])rank[rootx] += 1; } } }; class Solution { int Kruskal(vector<Edge> struct_edges, int node_num, int specified_edge=-1){ int weight = 0; int MST_edge_num = 0; unionfindSet uf(node_num); // cout << "specified_edge " << specified_edge << endl; if(specified_edge != -1){ int start = struct_edges[specified_edge].start, end = struct_edges[specified_edge].end; // cout << "insert:[" << start << "-" << end << "] root:" << uf.find_root(start) << " " << uf.find_root(end) << endl; uf.merge(start, end); MST_edge_num++; weight += struct_edges[specified_edge].weight; } for(int i = 0; i < struct_edges.size(); i++){ if(i == specified_edge)continue; int start = struct_edges[i].start, end = struct_edges[i].end; if(uf.find_root(start) != uf.find_root(end)){ // cout << "insert:[" << start << "-" << end << "] root:" << uf.find_root(start) << " " << uf.find_root(end) << endl; uf.merge(start, end); MST_edge_num++; weight += struct_edges[i].weight; } } // cout << "MST:" << weight << " " << MST_edge_num << endl; if(MST_edge_num == node_num - 1)return weight; return -1; } public: vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) { int edge_num = edges.size(); vector<vector<int>> result; if(edge_num < n - 1)return result; vector<Edge> struct_edges(edge_num); for(int i = 0; i < edge_num; i++){ struct_edges[i].index = i; struct_edges[i].start = edges[i][0]; struct_edges[i].end = edges[i][1]; struct_edges[i].weight = edges[i][2]; } // printStructArray(edge_num); sort(struct_edges.begin(), struct_edges.begin() + edge_num, cmp); // printStructArray(struct_edges); int min_weight = Kruskal(struct_edges, n); if(min_weight == -1)return result; vector<int> critical_edges; vector<int> non_critical_edges; for(int i = 0; i < edge_num; i++){ int weight = Kruskal(struct_edges, n, i); if(weight == min_weight){ // active edge struct Edge now_edge = struct_edges[i]; struct_edges.erase(struct_edges.begin() + i); // printStructArray(struct_edges); int now_weight = Kruskal(struct_edges, n); if(now_weight == min_weight){ non_critical_edges.push_back(now_edge.index); } else{ critical_edges.push_back(now_edge.index); } struct_edges.insert(struct_edges.begin() + i, now_edge); // printStructArray(struct_edges); } } sort(critical_edges.begin(), critical_edges.end()); sort(non_critical_edges.begin(), non_critical_edges.end()); result.push_back(critical_edges); result.push_back(non_critical_edges); return result; } };

效率很低:
在這裡插入圖片描述
優化一下:


struct Edge{
    int start, end;
    int weight;
    int index;
};

bool cmp(Edge x, Edge y){
    return x.weight < y.weight;
}

class unionfindSet{
public:
    vector<int> parent;
    vector<int> rank;

    unionfindSet(int n):parent(vector<int> (n)), rank(vector<int> (n)){
        for(int i = 0; i < n; i++){
            parent[i] = i;
        }
    }

    int find_root(int x){
        if(x != parent[x]){
            parent[x] = find_root(parent[x]);
        }
        return parent[x];
    }

    void merge(int x, int y){
        int rootx = find_root(x);
        int rooty = find_root(y);
        if(rootx != rooty){
            if(rank[rootx] < rank[rooty]){
                swap(rootx, rooty);
            }
            parent[rooty] = rootx;
            if(rank[rootx] == rank[rooty])rank[rootx] += 1;
        }
    }
};


class Solution {

    int Kruskal(vector<Edge> struct_edges, int node_num, int specified_edge=-1, int delete_edge=-1){
        int weight = 0;
        int MST_edge_num = 0;
        unionfindSet uf(node_num);
        if(specified_edge != -1){
            int start = struct_edges[specified_edge].start, end = struct_edges[specified_edge].end;
            uf.merge(start, end);
            MST_edge_num++;
            weight += struct_edges[specified_edge].weight;
        }
        for(int i = 0; i < struct_edges.size(); i++){
            if(i == specified_edge || i == delete_edge)continue;
            int start = struct_edges[i].start, end = struct_edges[i].end;
            if(uf.find_root(start) != uf.find_root(end)){
                uf.merge(start, end);
                MST_edge_num++;
                weight += struct_edges[i].weight;
            }
            if(MST_edge_num == node_num - 1)break;
        }
        if(MST_edge_num == node_num - 1)return weight;
        return -1;
    }

public:
    vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {
        int edge_num = edges.size();
        vector<vector<int>> result;
        if(edge_num < n - 1)return result;
        vector<Edge> struct_edges(edge_num);
        for(int i = 0; i < edge_num; i++){
            struct_edges[i].index = i;
            struct_edges[i].start = edges[i][0];
            struct_edges[i].end = edges[i][1];
            struct_edges[i].weight = edges[i][2];
        }

        sort(struct_edges.begin(), struct_edges.begin() + edge_num, cmp);
        int min_weight = Kruskal(struct_edges, n);
        if(min_weight == -1)return result;
        
        vector<int> critical_edges;
        vector<int> non_critical_edges;
        for(int i = 0; i < edge_num; i++){
            int weight = Kruskal(struct_edges, n, i);
            if(weight == min_weight){   // active edge
                int now_weight = Kruskal(struct_edges, n, -1, i);
                if(now_weight == min_weight){   // non-critical edge
                    non_critical_edges.push_back(struct_edges[i].index);
                }
                else{   // critical edge
                    critical_edges.push_back(struct_edges[i].index);
                }
            }
        }
        sort(critical_edges.begin(), critical_edges.end());
        sort(non_critical_edges.begin(), non_critical_edges.end());
        result.push_back(critical_edges);
        result.push_back(non_critical_edges);
        return result;
    }
};

優化了個寂寞,就這樣吧,累了
在這裡插入圖片描述