# subject

# Problem solution

n cities and the connection relationship between them can be regarded as a graph. The city is the node in the graph, and the connection relationship is the edge in the graph. The given matrix isConnected is the adjacency matrix of the graph, and the province is the connected component in the graph.

Calculating the total number of provinces is equivalent to calculating the number of connected components in the graph. It can be realized by depth first search or breadth first search, or by merging and searching sets.

## Solution 1: depth first search

[ideas]

Traverse all cities. For each city, if the city has not been visited, start the depth first search from the city, get the cities directly connected to the city through the matrix sConnected, and these cities belong to the same connected component as the city, and then continue the depth first search for these cities, Until all cities of the same connected component are visited, a province can be obtained. After traversing all cities, you can get the total number of connected components, that is, the total number of provinces.

[Code]

class Solution { public: //DFS void dfs(vector<vector<int>> &isConnected, vector<int> &visited, int provinces, int i) { for (int j = 0; j < provinces; j++) { if (isConnected[i][j] == 1 && !visited[j]) { visited[j] = 1; dfs(isConnected, visited, provinces, j); } } } int findCircleNum(vector<vector<int>>& isConnected) { int provinces = isConnected.size(); vector<int> visited(provinces); int ans = 0; for (int i = 0; i < provinces; i++) { if (!visited[i]) { ans++; dfs(isConnected, visited, provinces, i); } } return ans; } };

[complexity analysis]

- Time complexity: O ( n 2 ) O(n^2) O(n2), where n n n is the number of cities. Need to traverse the matrix n n Each element in n.
- Space complexity: O ( n ) O(n) O(n), where n n n is the number of cities. Array is required v i s i t e d visited Visited records whether each city has been visited. The length of the array is n n n. The depth of the recursive call stack will not exceed n n n.

## Solution 2: breadth first search

[ideas]

The total number of provinces can also be obtained by breadth first search. For each city, if the city has not been visited, start breadth first search from the city until all cities in the same connected component are visited to get a province.

[Code]

class Solution { public: int findCircleNum(vector<vector<int>>& isConnected) { int provinces = isConnected.size(); vector<int> visited(provinces); queue<int> que; int ans = 0; for (int i = 0; i < provinces; i++) { if (!visited[i]) { que.push(i); while (!que.empty()) { int j = que.front(); que.pop(); visited[j] = 1; for (int k = 0; k < provinces; k++) { if (isConnected[j][k] == 1 && !visited[k]) { que.push(k); } } } ans++; } } return ans; } };

[complexity analysis]

- Time complexity: O ( n 2 ) O(n^2) O(n2), where n n n is the number of cities. Each element in the isConnected matrix needs to be traversed.
- Space complexity: O ( n ) O(n) O(n), where n n n is the number of cities. You need to use the array visited to record whether each city has been accessed. The length of the array is n n n. The number of elements in the queue used by breadth first search will not exceed n n n.

## Solution 3: joint search set

[ideas]

Another way to calculate the number of connected components is to use union search set. Initially, each city belongs to different connected components. Traverse the matrix isConnected. If there is a connected relationship between two cities, they belong to the same connected component, and they are merged.

After traversing all the elements of the matrix isConnected, calculate the total number of connected components, that is, the total number of provinces.

[Code]

class Solution { private: void init(int n) { parent.resize(n); for (int i = 0; i < n; i++) parent[i] = i; } int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); } void merge(int p, int q) { int pp = find(p), pq = find(q); if (pp != pq) parent[pp] = pq; } vector<int> parent; public: int findCircleNum(vector<vector<int>>& isConnected) { int n = isConnected.size(); if (n == 0) return 0; int ans = n; init(n); for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { if (isConnected[i][j] == 1) { if (find(i) != find(j)) { ans--; parent[find(i)] = find(j); } } } } return ans; } };

[complexity analysis]

- Time complexity: O ( n 2 log n ) O(n^2 \log n) O(n2logn), where n n n is the number of cities. It needs to traverse half of all elements in the matrix isConnected, and the time complexity is O ( n 2 ) O(n^2) O(n2). If a connection relationship is encountered, you need to perform 2 searches and 1 merge at most 2 n 2 2n^2 2n2 lookups and maximum n 2 n^2 n2 merges, so the total time complexity is O ( 2 n 2 log n 2 ) = O ( n 2 log n ) O(2n^2 \log n^2)=O(n^2 \log n) O(2n2logn2)=O(n2logn). The merge set here uses path compression, but does not use rank merging. In the worst case, the time complexity is O ( n 2 log n ) O(n^2 \log n) O(n2logn), the average time complexity is still O ( n 2 α ( n ) ) O(n^2 \alpha (n)) O(n2 α (n)), where α \alpha α Is the inverse of the Ackerman function, α ( n ) \alpha (n) α (n) It can be considered a small constant.
- Space complexity: O ( n ) O(n) O(n), where n n n is the number of cities. You need to use the array parent to record the ancestors of the connected components to which each city belongs.