- Connecting Graph II
Given n nodes in a graph labeled from 1 to n. There is no edges in the graph at beginning.
You need to support the following method:
connect(a, b), an edge to connect node a and node b
query(a), Returns the number of connected component nodes which include node a.
Example
5 // n = 5
query(1) return 1
connect(1, 2)
query(1) return 2
connect(2, 4)
query(1) return 3
connect(1, 4)
query(1) return 3
思路:
经典并查集算法
注意:
- 在query()里面必须返回nodeNum[find(a)]而不是nodeNum[father[a]]。原因是当a的component跟另一个component合并时,father[a]可能还没更新。举例如下:
input case:
ConnectingGraph2(5)
query(1)
connect(1, 2)
query(1)
connect(2, 4) – connect(2,4)后,1的father[]还未更新
query(1) – 如果直接返回nodeSum[father[1]]则出错!!!
connect(1, 4)
query(1)
同样,connect()里面也不能用father[a],必须用find(a)。
2) path compression的条件也可以写成while(x2!=father[x2]),但稍慢。
3) connect()里面是father[fatherA]=fatherB,不要写成father[a]=father[b]或father[a]=fatherB之类的。
代码如下:
class ConnectingGraph2 {
public:
/*
* @param n: An integer
*/
ConnectingGraph2(int n) {
father.resize(n + 1);
nodeNum.resize(n + 1);
for (int i = 1; i <= n; ++i) {
father[i] = i;
nodeNum[i] = 1;
}
}
/*
* @param a: An integer
* @param b: An integer
* @return: nothing
*/
void connect(int a, int b) {
int rootA = find(a); //不能用father[a]
int rootB = find(b); //不能用father[b]
if (rootA != rootB) {
father[rootA] = rootB;
nodeNum[rootB] += nodeNum[rootA];
}
}
/*
* @param a: An integer
* @return: An integer
*/
int query(int a) {
// return nodeNum[father[a]]; //wrong!!!
return nodeNum[find(a)];
}
private:
vector<int> father;
vector<int> nodeNum;
//find the root of x
int find(int x) {
int x2 = x;
if (father[x] == x) return x;
while(father[x] != x) {
x = father[x];
}
//path compression
while (x2 != x) {
int temp = father[x2];
father[x2] = x;
x2 = temp;
}
return x;
}
};