裸并查集,并根据图论知识判断,如果边数大于等于顶点数减一,就一定可以改造成连通图。
// 因为边可以任意移动,所以只要边数大于等于计算机数减一,就一定可以连通
// 所需要的最小操作数等于连通分量数减一
class UnionFind {
public:
UnionFind(int _n): f(_n), setSize(_n, 1), n(_n), setCount(_n) {
for (int i = 0; i < n; ++i) {
f[i] = i;
}
}
int findf(int x) {
if (f[x] != x) {
f[x] = findf(f[x]);
}
return f[x];
}
void unionMerge(int x, int y) {
int fx = findf(x), fy = findf(y);
if (fx == fy) return;
if (setSize[fx] < setSize[fy]) swap(fx, fy);
f[fy] = fx;
setSize[fx] += setSize[fy];
setCount--;
}
int getSetCount() {
return setCount;
}
private:
vector<int> f, setSize;
int n, setCount;
};
class Solution {
public:
int makeConnected(int n, vector<vector<int>>& connections) {
int edgesNum = connections.size();
if (edgesNum < n - 1) return -1;
UnionFind uf(n);
for (int i = 0; i < edgesNum; ++i) {
uf.unionMerge(connections[i][0], connections[i][1]);
}
return uf.getSetCount() - 1;
}
};