
思路
基础的kruskal基础上区分两种边,首先求一下MST的Mcost:
- 关键边,删除该边,再求MST,若cost > Mcost (或者不连通,也满足大于)则该边为关键边
- 伪关键边,非关键边有可能是伪关键边,可以先将该边加入MST,然后继续kruskal, 若cost == Mcost吗,则为非关键边,否则“啥也不是边”
AC code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| class Solution { public: const static int inf = 0x3f3f3f3f; vector<int> p;
int find(int x){ return p[x] == x ? p[x] : p[x] = find(p[x]); }
int kruskal(int n, vector<vector<int>>& edges, vector<int>& del){ p.resize(n); for(int i = 0; i < n; i++) p[i] = i; int cnt = 0; int cost = 0; for(auto e : edges){ if(e == del) continue; int a = e[0], b = e[1], w = e[2]; int pa = find(a), pb = find(b); if(pa != pb){ p[pa] = pb; cnt++; cost += w; } } return cnt == n - 1 ? cost : inf; }
int rekruskal(int n, vector<vector<int>>& edges, vector<int>& del){ p.resize(n); for(int i = 0; i < n; i++) p[i] = i; p[del[0]] = del[1]; int cnt = 1; int cost = del[2]; for(auto e : edges){ if(e == del) continue; int a = e[0], b = e[1], w = e[2]; int pa = find(a), pb = find(b); if(pa != pb){ p[pa] = pb; cnt++; cost += w; } } return cnt == n - 1 ? cost : inf; }
vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) { int edgen = edges.size(); for(int i = 0; i < edgen; i++) edges[i].push_back(i); sort(edges.begin(), edges.end(), [&](const vector<int>& a, const vector<int>& b){ return a.at(2) < b.at(2); }); vector<int> del; int minCost = kruskal(n, edges, del); vector<vector<int>> res(2); for(auto e : edges){ del = e; int cost = kruskal(n, edges, del); if(cost > minCost) res[0].push_back(e[3]); else if(rekruskal(n, edges, del) == minCost) res[1].push_back(e[3]); } return res; } };
|