65
65
66
66
<!-- 这里可写通用的实现逻辑 -->
67
67
68
- 最小生成树问题。
68
+ ** 方法一:Kruskal 算法(最小生成树) **
69
69
70
- ** 方法一:Kruskal 算法 **
70
+ 我们假设有一个水井编号为 $0$,那么我们可以将每个房子与水井 $0$ 之间的连通性看作是一条边,每条边的权值为该房子建造水井的成本。同时,我们将每个房子之间的连通性也看作是一条边,每条边的权值为铺设管道的成本。这样一来,我们就可以将本题转化成求一张无向图的最小生成树的问题。
71
71
72
- 对于本题,可以将节点 0 视为水库,水库到房子间的成本等于房子内建造水井的成本。因此此题可以转换为最小生成树问题。
72
+ 我们可以使用 Kruskal 算法求出无向图的最小生成树。我们先把水井 $0$ 与房子之间的一条边加入 $pipes$ 数组中,然后将 $pipes$ 数组按照边权值从小到大排序。随后,我们遍历每一条边,如果这条边连接了不同的连通分量,我们就选用这条边,并将对应连通分量合并。如果当前的连通分量恰好为 $1$,那么我们就找到了最小生成树,此时的答案即为当前边权值,我们将其返回即可。
73
+
74
+ 时间复杂度 $O((m + n) \times \log (m + n))$,空间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别是 $pipes$ 数组和 $wells$ 数组的长度。
73
75
74
76
<!-- tabs:start -->
75
77
@@ -82,27 +84,26 @@ class Solution:
82
84
def minCostToSupplyWater (
83
85
self , n : int , wells : List[int ], pipes : List[List[int ]]
84
86
) -> int :
85
- for i, w in enumerate (wells):
86
- pipes.append([0 , i + 1 , w])
87
- pipes.sort(key = lambda x : x[2 ])
88
-
89
- p = list (range (n + 1 ))
90
-
91
- def find (x ):
87
+ def find (x : int ) -> int :
92
88
if p[x] != x:
93
89
p[x] = find(p[x])
94
90
return p[x]
95
91
96
- res = 0
97
- for u, v, w in pipes:
98
- if find(u) == find(v):
92
+ for i, w in enumerate (wells, 1 ):
93
+ pipes.append([0 , i, w])
94
+ pipes.sort(key = lambda x : x[2 ])
95
+ p = list (range (n + 1 ))
96
+ ans = 0
97
+ for i, j, c in pipes:
98
+ pa, pb = find(i), find(j)
99
+ if pa == pb:
99
100
continue
100
- p[find(u) ] = find(v)
101
- res += w
101
+ p[pa ] = pb
102
+ ans += c
102
103
n -= 1
103
104
if n == 0 :
104
105
break
105
- return res
106
+ return ans
106
107
```
107
108
108
109
### ** Java**
@@ -114,32 +115,32 @@ class Solution {
114
115
private int [] p;
115
116
116
117
public int minCostToSupplyWater (int n , int [] wells , int [][] pipes ) {
117
- int [][] all = new int [pipes . length + n][ 3 ];
118
- int idx = 0 ;
119
- for (int [] pipe : pipes) {
120
- all[idx ++ ] = pipe;
118
+ var nums = new int [n + pipes . length][ 0 ];
119
+ int j = 0 ;
120
+ for (var pipe : pipes) {
121
+ nums[j ++ ] = pipe;
121
122
}
122
- for (int j = 0 ; j < n; ++ j ) {
123
- all[idx ++ ] = new int [] {0 , j + 1 , wells[j ]};
123
+ for (int i = 0 ; i < n; ++ i ) {
124
+ nums[j ++ ] = new int []{0 , i + 1 , wells[i ]};
124
125
}
126
+ Arrays . sort(nums, (a, b) - > a[2 ] - b[2 ]);
125
127
p = new int [n + 1 ];
126
- for (int i = 0 ; i < p . length ; ++ i) {
128
+ for (int i = 1 ; i <= n ; ++ i) {
127
129
p[i] = i;
128
130
}
129
- Arrays . sort(all, Comparator . comparingInt(a - > a[ 2 ])) ;
130
- int res = 0 ;
131
- for ( int [] e : all) {
132
- if (find(e[ 0 ]) == find(e[ 1 ]) ) {
131
+ int ans = 0 ;
132
+ for ( var x : nums) {
133
+ int pa = find(x[ 0 ]), pb = find(x[ 1 ]);
134
+ if (pa == pb ) {
133
135
continue ;
134
136
}
135
- p[find(e[0 ])] = find(e[1 ]);
136
- res += e[2 ];
137
- -- n;
138
- if (n == 0 ) {
137
+ ans += x[2 ];
138
+ p[pa] = pb;
139
+ if (-- n == 0 ) {
139
140
break ;
140
141
}
141
142
}
142
- return res ;
143
+ return ans ;
143
144
}
144
145
145
146
private int find (int x ) {
@@ -156,69 +157,107 @@ class Solution {
156
157
``` cpp
157
158
class Solution {
158
159
public:
159
- vector<int > p;
160
-
161
160
int minCostToSupplyWater(int n, vector<int >& wells, vector<vector<int >>& pipes) {
162
- p.resize(n + 1);
163
- for (int i = 0; i < p.size(); ++i) p [i] = i ;
164
- for (int i = 0; i < n; ++i) pipes.push_back({0, i + 1, wells[i]});
165
- sort(pipes.begin(), pipes.end(), [](const auto & a, const auto & b) {
161
+ for (int i = 0; i < n; ++i) {
162
+ pipes.push_back({0, i + 1, wells [ i] }) ;
163
+ }
164
+ sort(pipes.begin(), pipes.end(), [ ] (const vector< int > & a, const vector< int > & b) {
166
165
return a[ 2] < b[ 2] ;
167
166
});
168
- int res = 0;
169
- for (auto e : pipes) {
170
- if (find(e[0]) == find(e[1])) continue;
171
- p[find(e[0])] = find(e[1]);
172
- res += e[2];
173
- --n;
174
- if (n == 0) break;
167
+ int p[ n + 1] ;
168
+ iota(p, p + n + 1, 0);
169
+ function<int(int)> find = [ &] (int x) {
170
+ if (p[ x] != x) {
171
+ p[ x] = find(p[ x] );
172
+ }
173
+ return p[ x] ;
174
+ };
175
+ int ans = 0;
176
+ for (const auto& x : pipes) {
177
+ int pa = find(x[ 0] ), pb = find(x[ 1] );
178
+ if (pa == pb) {
179
+ continue;
180
+ }
181
+ p[ pa] = pb;
182
+ ans += x[ 2] ;
183
+ if (--n == 0) {
184
+ break;
185
+ }
175
186
}
176
- return res;
177
- }
178
-
179
- int find (int x) {
180
- if (p[ x] != x) p[ x] = find(p[ x] );
181
- return p[ x] ;
187
+ return ans;
182
188
}
183
189
};
184
190
```
185
191
186
192
### **Go**
187
193
188
194
```go
189
- var p []int
190
-
191
- func minCostToSupplyWater(n int, wells []int, pipes [][]int) int {
192
- p = make([]int, n+1)
193
- for i := 0; i < len(p); i++ {
194
- p[i] = i
195
- }
195
+ func minCostToSupplyWater(n int, wells []int, pipes [][]int) (ans int) {
196
196
for i, w := range wells {
197
197
pipes = append(pipes, []int{0, i + 1, w})
198
198
}
199
- sort.Slice(pipes, func(i, j int) bool {
200
- return pipes[i][2] < pipes[j][2]
201
- })
202
- res := 0
203
- for _, e := range pipes {
204
- if find(e[0]) == find(e[1]) {
199
+ sort.Slice(pipes, func(i, j int) bool { return pipes[i][2] < pipes[j][2] })
200
+ p := make([]int, n+1)
201
+ for i := range p {
202
+ p[i] = i
203
+ }
204
+ var find func(int) int
205
+ find = func(x int) int {
206
+ if p[x] != x {
207
+ p[x] = find(p[x])
208
+ }
209
+ return p[x]
210
+ }
211
+
212
+ for _, x := range pipes {
213
+ pa, pb := find(x[0]), find(x[1])
214
+ if pa == pb {
205
215
continue
206
216
}
207
- p[find(e[0])] = find(e[1])
208
- res += e [2]
217
+ p[pa] = pb
218
+ ans += x [2]
209
219
n--
210
220
if n == 0 {
211
221
break
212
222
}
213
223
}
214
- return res
224
+ return
215
225
}
226
+ ```
216
227
217
- func find(x int) int {
218
- if p[x] != x {
219
- p[x] = find(p[x])
220
- }
221
- return p[x]
228
+ ### ** TypeScript**
229
+
230
+ ``` ts
231
+ function minCostToSupplyWater(
232
+ n : number ,
233
+ wells : number [],
234
+ pipes : number [][],
235
+ ): number {
236
+ for (let i = 0 ; i < n ; ++ i ) {
237
+ pipes .push ([0 , i + 1 , wells [i ]]);
238
+ }
239
+ pipes .sort ((a , b ) => a [2 ] - b [2 ]);
240
+ const p = new Array (n + 1 ).fill (0 ).map ((_ , i ) => i );
241
+ const find = (x : number ): number => {
242
+ if (p [x ] !== x ) {
243
+ p [x ] = find (p [x ]);
244
+ }
245
+ return p [x ];
246
+ };
247
+ let ans = 0 ;
248
+ for (const [i, j, c] of pipes ) {
249
+ const pa = find (i );
250
+ const pb = find (j );
251
+ if (pa === pb ) {
252
+ continue ;
253
+ }
254
+ p [pa ] = pb ;
255
+ ans += c ;
256
+ if (-- n === 0 ) {
257
+ break ;
258
+ }
259
+ }
260
+ return ans ;
222
261
}
223
262
```
224
263
0 commit comments