难度:困难。
标签:深度优先搜索,并查集。
看了提示,需要用Kruskal算法来计算最小生成树,方法如下:
- 计算最小生成树的权重为 m i n W e i g h t minWeight minWeight。
- 遍历所有边,指定以当前边为最小生成树中的边来构建最小生成树,若构建成功且当 n o w W e i g h t = = m i n W e i g h t nowWeight == minWeight nowWeight==minWeight 时,则该边为有效边;否则(构建不成功,或构建成功权重变大)为无效边。
- 当边为有效边时,继续,进一步判断其为关键边或非关键边。
- 将当前边删除用其余边来构建最小生成树,若构建成功且 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;
}
};
优化了个寂寞,就这样吧,累了