2023-08-04: There are n houses in the village. We hope to supply water to all houses by building wells and laying pipes. For each house i, we have two alternative water supply schemes: One is to build a well directly in the house with a cost of wells[i -

2023-08-04: There are n houses in the village

We want to supply water to all the houses by building wells and laying pipes.

For each house i, we have two alternative water supply schemes:

One is to build a well directly inside the house

The cost is wells[i - 1] (note the -1 because the index starts from 0)

The other is to pipe water from another well

The array pipes gives the cost of laying pipes between houses

where each pipes[j] = [house1j, house2j, costj]

Represents the cost of piping house1j and house2j together. Connections are bidirectional.

Return the lowest total cost of providing water to all houses.

This question is very frequent, attract attention,

It is not difficult in itself, just transform it into a minimum spanning tree problem.

Input: n = 3, wells = [1,2,2], pipes = [[1,2,1],[2,3,1]].

Output: 3.

From Xiaohongshu and ByteDance.

Answer 2023-08-04:

The general process is as follows:

1. Initialization:

1.1. Create edge array edges to store pipeline information.

1.2. Treat each house i as an independent connected component, and initialize the parent array father[i] to be i.

1.3. Create the size array size[i] of each house and initialize it to 1.

1.4. Create an auxiliary array help for path compression.

2. Build an edge array:

2.1. Add wells[i-1], the cost of building wells in each house i, into the edge array edges.

2.2. Add the information of each pipeline [house1j, house2j, costj] to the edge array edges.

3. Sort the edge array:

3.1. Sort the edge array edges according to the cost of the edges from small to large.

4. Build and check:

4.1. Call the build(n) function to initialize and search.

5. Construction of the minimum spanning tree and calculation of the minimum total cost:
5.1. Initialize ans = 0 to record the minimum total cost.

5.2. Traversing the edge array edges, for each edge edges[i], perform the following steps:

5.2.1. Determine whether the two nodes of edges[i] are connected (use the find() function in the union):

5.2.1.1. If not connected, merge the two nodes (using the union() function in the union search set).

5.2.1.2. At the same time, add the cost edges[i][2] of this edge to the total cost ans.

6. Return the minimum total cost ans.

Total time complexity: O((n+m)log(n+m)), where n is the number of houses and m is the number of pipes, because the edge array is sorted.

Total space complexity: O(n+m), where n is the number of houses and m is the number of pipes (number of edges).

The complete code of go is as follows:

package main

import (
	"fmt"
	"sort"
)

const MAXN = 10010

var edges [][3]int
var esize int
var father [MAXN]int
var size [MAXN]int
var help [MAXN]int

func build(n int) {
    
    
	for i := 0; i <= n; i++ {
    
    
		father[i] = i
		size[i] = 1
	}
}

func find(i int) int {
    
    
	s := 0
	for i != father[i] {
    
    
		help[s] = i
		i = father[i]
		s++
	}
	for s > 0 {
    
    
		s--
		father[help[s]] = i
	}
	return i
}

func union(i, j int) bool {
    
    
	f1 := find(i)
	f2 := find(j)
	if f1 != f2 {
    
    
		if size[f1] >= size[f2] {
    
    
			father[f2] = f1
			size[f1] += size[f2]
		} else {
    
    
			father[f1] = f2
			size[f2] += size[f1]
		}
		return true
	}
	return false
}

func minCostToSupplyWater(n int, wells []int, pipes [][]int) int {
    
    
	esize = 0
	for i := 0; i < n; i++ {
    
    
		edges = append(edges, [3]int{
    
    0, i + 1, wells[i]})
		esize++
	}
	for i := 0; i < len(pipes); i++ {
    
    
		edges = append(edges, [3]int{
    
    pipes[i][0], pipes[i][1], pipes[i][2]})
		esize++
	}
	sort.Slice(edges, func(i, j int) bool {
    
    
		return edges[i][2] < edges[j][2]
	})
	build(n)
	ans := 0
	for i := 0; i < esize; i++ {
    
    
		if union(edges[i][0], edges[i][1]) {
    
    
			ans += edges[i][2]
		}
	}
	return ans
}

func main() {
    
    
	n := 3
	wells := []int{
    
    1, 2, 2}
	pipes := [][]int{
    
    {
    
    1, 2, 1}, {
    
    2, 3, 1}}

	result := minCostToSupplyWater(n, wells, pipes)
	fmt.Println(result)
}

insert image description here

The rust code is as follows:

const MAXN: i32 = 10010;

static mut EDGES: [[i32; 3]; (MAXN << 1) as usize] = [[0; 3]; (MAXN << 1) as usize];
static mut ESIZE: i32 = 0;

static mut FATHER: [i32; MAXN as usize] = [0; MAXN as usize];
static mut SIZE: [i32; MAXN as usize] = [0; MAXN as usize];
static mut HELP: [i32; MAXN as usize] = [0; MAXN as usize];

fn build(n: i32) {
    
    
    for i in 0..=n {
    
    
        unsafe {
    
    
            FATHER[i as usize] = i;
            SIZE[i as usize] = 1;
        }
    }
}

fn find(i: i32) -> i32 {
    
    
    let mut s = 0;
    unsafe {
    
    
        let mut index = i;
        while index != FATHER[index as usize] {
    
    
            HELP[s] = index;
            index = FATHER[index as usize];
            s += 1;
        }
        while s > 0 {
    
    
            s -= 1;
            FATHER[HELP[s] as usize] = index;
        }
        return index;
    }
}

fn union(i: i32, j: i32) -> bool {
    
    
    let f1 = find(i);
    let f2 = find(j);
    unsafe {
    
    
        if f1 != f2 {
    
    
            if SIZE[f1 as usize] >= SIZE[f2 as usize] {
    
    
                FATHER[f2 as usize] = f1;
                SIZE[f1 as usize] += SIZE[f2 as usize];
            } else {
    
    
                FATHER[f1 as usize] = f2;
                SIZE[f2 as usize] += SIZE[f1 as usize];
            }
            return true;
        } else {
    
    
            return false;
        }
    }
}

fn min_cost_to_supply_water(n: i32, wells: &[i32], pipes: &[[i32; 3]]) -> i32 {
    
    
    unsafe {
    
    
        ESIZE = 0;
        for i in 0..n {
    
    
            EDGES[ESIZE as usize][0] = 0;
            EDGES[ESIZE as usize][1] = i + 1;
            EDGES[ESIZE as usize][2] = wells[i as usize];
            ESIZE += 1;
        }
        for i in 0..pipes.len() {
    
    
            EDGES[ESIZE as usize][0] = pipes[i][0] as i32;
            EDGES[ESIZE as usize][1] = pipes[i][1] as i32;
            EDGES[ESIZE as usize][2] = pipes[i][2];
            ESIZE += 1;
        }
        EDGES[0..ESIZE as usize].sort_by(|a, b| a[2].cmp(&b[2]));
        build(n);
        let mut ans = 0;
        for i in 0..ESIZE {
    
    
            if union(EDGES[i as usize][0], EDGES[i as usize][1]) {
    
    
                ans += EDGES[i as usize][2];
            }
        }
        return ans;
    }
}

fn main() {
    
    
    let n = 3;
    let wells = [1, 2, 2];
    let pipes = [[1, 2, 1], [2, 3, 1]];
    let result = min_cost_to_supply_water(n, &wells, &pipes);
    println!("Minimum cost to supply water: {}", result);
}

insert image description here

The complete c++ code is as follows:

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
using namespace std;

const int MAXN = 10010;
vector<array<int, 3>> edges;
int father[MAXN];
int size2[MAXN];
int help[MAXN];

void build(int n) {
    
    
    for (int i = 0; i <= n; i++) {
    
    
        father[i] = i;
        size2[i] = 1;
    }
}

int find(int i) {
    
    
    int s = 0;
    while (i != father[i]) {
    
    
        help[s++] = i;
        i = father[i];
    }
    while (s > 0) {
    
    
        father[help[--s]] = i;
    }
    return i;
}

bool unionSet(int i, int j) {
    
    
    int f1 = find(i);
    int f2 = find(j);
    if (f1 != f2) {
    
    
        if (size2[f1] >= size2[f2]) {
    
    
            father[f2] = f1;
            size2[f1] += size2[f2];
        }
        else {
    
    
            father[f1] = f2;
            size2[f2] += size2[f1];
        }
        return true;
    }
    else {
    
    
        return false;
    }
}

int minCostToSupplyWater(int n, vector<int>& wells, vector<vector<int>>& pipes) {
    
    
    edges.clear();
    for (int i = 0; i < n; i++) {
    
    
        edges.push_back({
    
     0, i + 1, wells[i] });
    }
    for (int i = 0; i < pipes.size(); i++) {
    
    
        edges.push_back({
    
     pipes[i][0], pipes[i][1], pipes[i][2] });
    }
    sort(edges.begin(), edges.end(), [](const array<int, 3>& a, const array<int, 3>& b) {
    
    
        return a[2] < b[2];
        });
    build(n);
    int ans = 0;
    for (int i = 0; i < edges.size(); i++) {
    
    
        if (unionSet(edges[i][0], edges[i][1])) {
    
    
            ans += edges[i][2];
        }
    }
    return ans;
}

int main() {
    
    
    int n = 3;
    vector<int> wells = {
    
     1, 2, 2 };
    vector<vector<int>> pipes = {
    
     {
    
    1, 2, 1}, {
    
    2, 3, 1} };
    int result = minCostToSupplyWater(n, wells, pipes);
    cout << "Minimum cost to supply water: " << result << endl;
    return 0;
}

insert image description here

The complete code of c is as follows:

#include <stdio.h>
#include <stdlib.h>

#define MAXN 10010

int edges[MAXN << 1][3];
int esize;
int father[MAXN];
int size[MAXN];
int help[MAXN];

void build(int n) {
    
    
    for (int i = 0; i <= n; i++) {
    
    
        father[i] = i;
        size[i] = 1;
    }
}

int find(int i) {
    
    
    int s = 0;
    while (i != father[i]) {
    
    
        help[s++] = i;
        i = father[i];
    }
    while (s > 0) {
    
    
        father[help[--s]] = i;
    }
    return i;
}

int union2(int i, int j) {
    
    
    int f1 = find(i);
    int f2 = find(j);
    if (f1 != f2) {
    
    
        if (size[f1] >= size[f2]) {
    
    
            father[f2] = f1;
            size[f1] += size[f2];
        }
        else {
    
    
            father[f1] = f2;
            size[f2] += size[f1];
        }
        return 1;
    }
    else {
    
    
        return 0;
    }
}

int minCostToSupplyWater(int n, int wells[], int pipes[][3], int pipesSize) {
    
    
    esize = 0;
    for (int i = 0; i < n; i++, esize++) {
    
    
        edges[esize][0] = 0;
        edges[esize][1] = i + 1;
        edges[esize][2] = wells[i];
    }
    for (int i = 0; i < pipesSize; i++, esize++) {
    
    
        edges[esize][0] = pipes[i][0];
        edges[esize][1] = pipes[i][1];
        edges[esize][2] = pipes[i][2];
    }

    // Sort edges based on the third column (weights)
    for (int i = 0; i < esize; i++) {
    
    
        for (int j = 0; j < esize - 1; j++) {
    
    
            if (edges[j][2] > edges[j + 1][2]) {
    
    
                int temp[3];
                temp[0] = edges[j][0];
                temp[1] = edges[j][1];
                temp[2] = edges[j][2];
                edges[j][0] = edges[j + 1][0];
                edges[j][1] = edges[j + 1][1];
                edges[j][2] = edges[j + 1][2];
                edges[j + 1][0] = temp[0];
                edges[j + 1][1] = temp[1];
                edges[j + 1][2] = temp[2];
            }
        }
    }

    build(n);
    int ans = 0;
    for (int i = 0; i < esize; i++) {
    
    
        if (union2(edges[i][0], edges[i][1])) {
    
    
            ans += edges[i][2];
        }
    }
    return ans;
}

int main() {
    
    
    int n = 3;
    int wells[] = {
    
     1, 2, 2 };
    int pipes[][3] = {
    
     {
    
    1, 2, 1}, {
    
    2, 3, 1} };
    int pipesSize = sizeof(pipes) / sizeof(pipes[0]);

    int result = minCostToSupplyWater(n, wells, pipes, pipesSize);
    printf("Minimum cost to supply water: %d\n", result);

    return 0;
}

insert image description here

Guess you like

Origin blog.csdn.net/weixin_48502062/article/details/132099532