Skip to content

[pull] master from wisdompeak:master #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,8 @@
[1168.Optimize-Water-Distribution-in-a-Village](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/1168.Optimize-Water-Distribution-in-a-Village) (H-)
[1489.Find-Critical-and-Pseudo-Critical-Edges-in-Minimum-Spanning-Tree](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/1489.Find-Critical-and-Pseudo-Critical-Edges-in-Minimum-Spanning-Tree) (H)
[1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable) (H-)
[1584.Min-Cost-to-Connect-All-Points](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/1584.Min-Cost-to-Connect-All-Points) (H-)
[1584.Min-Cost-to-Connect-All-Points](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/1584.Min-Cost-to-Connect-All-Points) (H-)
[3600.Maximize-Spanning-Tree-Stability-with-Upgrades](https://github.com/wisdompeak/LeetCode/tree/master/Union_Find/3600.Maximize-Spanning-Tree-Stability-with-Upgrades) (H)

#### [Recursion](https://github.com/wisdompeak/LeetCode/tree/master/Recursion)
[087.Scramble-String](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/087.Scramble-String) (H-)
Expand Down Expand Up @@ -1704,7 +1705,8 @@
[Graph](https://github.com/wisdompeak/LeetCode/tree/master/Template/Graph)
[Bit_Manipulation](https://github.com/wisdompeak/LeetCode/tree/master/Template/Bit_manipulation)
[RB_Tree](https://github.com/wisdompeak/LeetCode/tree/master/Template/RB_Tree)
[Binary_Lift](https://github.com/wisdompeak/LeetCode/tree/master/Template/Binary_Lift)
[Binary_Lift](https://github.com/wisdompeak/LeetCode/tree/master/Template/Binary_Lift)
[Union_Find](https://github.com/wisdompeak/LeetCode/tree/master/Template/Union_Find)
[二维子矩阵求和](https://github.com/wisdompeak/LeetCode/tree/master/Template/Sub_Rect_Sum_2D)
[二维差分数组](https://github.com/wisdompeak/LeetCode/tree/master/Template/Diff_Array_2D)
[CPP_LANG](https://github.com/wisdompeak/LeetCode/tree/master/Template/CPP_LANG)
Expand Down
23 changes: 23 additions & 0 deletions Template/Union_Find/union_find.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
struct DSU {
vector<int> p, r;
DSU(int n): p(n,-1), r(n,0) {
iota(p.begin(), p.end(), 0);
}
int find(int x) {
return p[x]==x ? x : p[x]=find(p[x]);
}
bool unite(int a, int b) {
a = find(a); b = find(b);
if (a == b) return false;
if (r[a] < r[b]) swap(a,b);
p[b] = a;
if (r[a]==r[b]) ++r[a];
return true;
}
};

int main {
DSU dsu(n);
dsu.unite(u,v);
if (dsu.find(u)==dsu.find(v) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
class Solution {
public:
struct DSU {
vector<int> p, r;
DSU(int n): p(n,-1), r(n,0) {
iota(p.begin(), p.end(), 0);
}
int find(int x) {
return p[x]==x ? x : p[x]=find(p[x]);
}
bool unite(int a, int b) {
a = find(a); b = find(b);
if (a == b) return false;
if (r[a] < r[b]) swap(a,b);
p[b] = a;
if (r[a]==r[b]) ++r[a];
return true;
}
};

bool isOK(int T, int n, vector<vector<int>>& edges, int k) {
DSU dsu(n);
int count = 0;
int upgrade = 0;

vector<vector<int>>candidates; // upgrade, u,v
for (auto& e: edges) {
int u = e[0], v = e[1], s = e[2], must = e[3];
if (must) {
if (s<T) return false;
dsu.unite(u,v);
count++;
} else {
if (s>=T)
candidates.push_back({0, u, v});
else if (2*s>=T)
candidates.push_back({1, u, v});
}
}

sort(candidates.begin(), candidates.end());

for (auto& cand: candidates) {
int u = cand[1], v = cand[2];
if (count==n-1) break;
if (dsu.find(u)!=dsu.find(v)) {
dsu.unite(u,v);
count++;
upgrade += cand[0];
if (upgrade > k) return false;
}
}

for (int i=0; i<n; i++)
if (dsu.find(i)!=dsu.find(0))
return false;

return count==n-1;
}

int maxStability(int n, vector<vector<int>>& edges, int k) {
int lo = 1, hi = 1e5*2;
while (lo < hi) {
int mid = hi-(hi-lo)/2;
if (isOK(mid, n, edges, k))
lo = mid;
else
hi = mid-1;
}
if (isOK(lo, n, edges, k))
return lo;
else
return -1;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### 3600.Maximize-Spanning-Tree-Stability-with-Upgrades

突破口是二分搜值。如果猜测全局最小的stability是T的话,尝试能否用最小生成树的方法构造出一棵树来。

当固定全局最小的stability是T之后,那么哪些edge能用哪些不能用就一目了然了。对于must的那些边,如果存在stability小于T的,那么显然无解。对于非must的边,如果`2*stability<T`,那么必然排除作为构造树的候选;反之就可以作为候选,同时我们需要根据2s和T的比较,标注这条边“是否需要upgrade”。

有了所有的候选边,我们就可以用Kruskal算法构造“最小生成树”。只不过这里优化的不是总边的权重,而是“upgrade的次数”。我们将所有边按照“是否需要upgrade”排序即可(其实就是0或者1),优先选用不需要upgrade的边实现更多的union。如果发现一个候选边的两个端点已经union在一起了,那么这条边其实就可以放心地舍弃而没有任何副作用。注意处理完所有的边之后还需要判断两点:是否恰好用到了n-1条边(否则说明可能有环),是否所有的点的find都相同(否则说明可能有不联通的区域)。