6.14华为OD机试真题 新系统 - 分析电网负载均衡 (Java/Py/C/C++/Js/Go)

分析电网负载均衡

2026 华为OD机试真题 6月14日华为OD上机新系统考试真题 200 分题型

点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解

题目描述

某电力公司管理N个变电站节点(编号0~N-1),节点间通过M条输电线路连接,相连节点属于同一供电区。定义供电区的不均衡度=区内最大负载与最小负载之差 ×节点数。请找出不均衡度最大的供电区,输出其不均衡度。若无有效供电区(节点数<2或M=0),输出-1。

输入描述

整型数组loads,长度为N,表示编号0~N-1的节点负载(MW); 二维整型数组edges,每行2个整数,表示该线路连接的两个节点编号,共M行。

约束:

1 ≤ N ≤ 100 0 ≤ M ≤ N×(N-1)/2 0 ≤ loads[i] ≤ 10000 0 ≤ edges[j][0], edges[j][1] ≤ N-1 edges[j][0] ≠ edges[j][1],无重复边

输出描述

整型,表示所有供电区中不均衡度的最大值。若无有效供电区,输出-1。

示例1

输入

[100,200,150,50,300],[[0,1],[1,2],[3,4]]

输出

500

说明

边(0,1)(1,2)将节点0,1,2连为供电区A,负载[100,200,150],不均衡度=(200-100)×3=300 边(3,4)将节点3,4连为供电区B,负载[50,300],不均衡度=(300-50)×2=500 供电区B不均衡度更大,输出500

示例2

输入

[80,90,80,90],[[0,1],[1,2],[2,3]]

输出

40

说明

4个节点连为1个供电区,不均衡度=(90-80)×4=40,输出40

示例3

输入

[100,200,300],[]

输出

-1

说明

每个节点独立,不构成有效供电区,输出-1

解题思路

核心思想

本题是一个 图的连通分量 问题,需要使用 并查集(Union-Find) 算法来找出所有供电区,然后计算每个供电区的不均衡度。

算法步骤:

  1. 初始化并查集,每个节点独立为一个集合
  2. 遍历所有边,将相连的节点合并到同一个集合
  3. 将同一集合的节点分组
  4. 对每个分组:
    • 节点数 < 2 的跳过(不是有效供电区)
    • 计算负载最大值和最小值
    • 计算不均衡度 = (最大值 - 最小值) × 节点数
  5. 返回最大不均衡度,如果没有有效供电区返回 -1

并查集核心操作:

  • find(x):查找节点 x 所属集合的根节点(路径压缩优化)
  • union(a, b):合并节点 a 和 b 所在的集合

复杂度分析

  • 时间复杂度:O(N + M × α(N)),α 为 Ackermann 函数的反函数,近似常数
  • 空间复杂度:O(N),存储父节点数组

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        String line = scanner.nextLine().trim();
        int splitIndex = line.indexOf("],");
        String loadsLine = line.substring(0, splitIndex + 1);
        String edgesLine = line.substring(splitIndex + 2);

        loadsLine = loadsLine.replace("[", "").replace("]", "");
        String[] loadStrs = loadsLine.split(",");
        int[] loads = new int[loadStrs.length];
        for (int i = 0; i < loadStrs.length; i++) {
            loads[i] = Integer.parseInt(loadStrs[i].trim());
        }

        int[][] edges;
        if (edgesLine.equals("[]")) {
            edges = new int[0][0];
        } else {
            edgesLine = edgesLine.replace("[[", "").replace("]]", "");
            String[] edgePairs = edgesLine.split("],\\[");
            edges = new int[edgePairs.length][2];
            for (int i = 0; i < edgePairs.length; i++) {
                String[] nodes = edgePairs[i].split(",");
                edges[i][0] = Integer.parseInt(nodes[0].trim());
                edges[i][1] = Integer.parseInt(nodes[1].trim());
            }
        }

        int result = maxZoneImbalance(loads, edges);
        System.out.println(result);
    }

    public static int maxZoneImbalance(int[] loads, int[][] edges) {
        int nodeCount = loads.length;

        if (edges.length == 0) {
            return -1;
        }

        int[] parent = new int[nodeCount];
        for (int i = 0; i < nodeCount; i++) {
            parent[i] = i;
        }

        java.util.function.IntFunction<Integer> find = (x) -> {
            while (parent[x] != x) {
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        };

        java.util.function.BiConsumer<Integer, Integer> union = (a, b) -> {
            int rootA = find.apply(a);
            int rootB = find.apply(b);
            if (rootA != rootB) {
                parent[rootB] = rootA;
            }
        };

        for (int[] edge : edges) {
            union.accept(edge[0], edge[1]);
        }

        Map<Integer, List<Integer>> groups = new HashMap<>();
        for (int i = 0; i < nodeCount; i++) {
            int root = find.apply(i);
            groups.computeIfAbsent(root, k -> new ArrayList<>()).add(i);
        }

        int answer = -1;
        for (List<Integer> nodes : groups.values()) {
            if (nodes.size() < 2) {
                continue;
            }

            int maxLoad = Integer.MIN_VALUE;
            int minLoad = Integer.MAX_VALUE;
            for (int node : nodes) {
                maxLoad = Math.max(maxLoad, loads[node]);
                minLoad = Math.min(minLoad, loads[node]);
            }

            int imbalance = (maxLoad - minLoad) * nodes.size();
            answer = Math.max(answer, imbalance);
        }

        return answer;
    }
}

Python

def max_zone_imbalance(loads, edges):
    n = len(loads)
    if not edges:
        return -1
    parent = list(range(n))
    
    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x
    
    def union(a, b):
        ra = find(a)
        rb = find(b)
        if ra != rb:
            parent[rb] = ra
    
    for u, v in edges:
        union(u, v)
    
    groups = {}
    for i in range(n):
        root = find(i)
        groups.setdefault(root, []).append(i)
    
    ans = -1
    for nodes in groups.values():
        if len(nodes) < 2:
            continue
        max_load = max(loads[i] for i in nodes)
        min_load = min(loads[i] for i in nodes)
        imbalance = (max_load - min_load) * len(nodes)
        if imbalance > ans:
            ans = imbalance
    return ans

import sys

line = sys.stdin.readline().strip()
if not line:
    sys.exit()
idx = line.index("],")
loads_part = line[:idx + 1]
edges_part = line[idx + 2:]

loads_part = loads_part.strip("[]")
loads = [int(x.strip()) for x in loads_part.split(",") if x.strip()]

if edges_part.strip() == "[]":
    edges = []
else:
    inner = edges_part.strip("[]")
    pair_strs = inner.split("],[")
    edges = []
    for pair in pair_strs:
        a, b = pair.split(",")
        edges.append([int(a.strip()), int(b.strip())])

print(max_zone_imbalance(loads, edges))

JavaScript

function maxZoneImbalance(loads, edges) {
    const n = loads.length;
    if (edges.length === 0) return -1;
    const parent = Array.from({ length: n }, (_, i) => i);
    function find(x) {
        while (parent[x] !== x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }
    for (const [u, v] of edges) {
        const ru = find(u);
        const rv = find(v);
        if (ru !== rv) parent[rv] = ru;
    }
    const groups = new Map();
    for (let i = 0; i < n; i++) {
        const r = find(i);
        if (!groups.has(r)) groups.set(r, []);
        groups.get(r).push(i);
    }
    let ans = -1;
    for (const nodes of groups.values()) {
        if (nodes.length < 2) continue;
        let maxLoad = -Infinity;
        let minLoad = Infinity;
        for (const node of nodes) {
            const v = loads[node];
            if (v > maxLoad) maxLoad = v;
            if (v < minLoad) minLoad = v;
        }
        const imbalance = (maxLoad - minLoad) * nodes.length;
        if (imbalance > ans) ans = imbalance;
    }
    return ans;
}

const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.on('line', (line) => {
    line = line.trim();
    const idx = line.indexOf('],');
    const loadsPart = line.substring(0, idx + 1);
    const edgesPart = line.substring(idx + 2);

    const loadsStr = loadsPart.replace(/[\[\]]/g, '');
    const loads = loadsStr.split(',').map(s => parseInt(s.trim())).filter(x => !isNaN(x));

    let edges;
    if (edgesPart.trim() === '[]') {
        edges = [];
    } else {
        const inner = edgesPart.replace(/^\[\[|\]\]$/g, '');
        const pairStrs = inner.split('],[');
        edges = pairStrs.map(pair => pair.split(',').map(n => parseInt(n.trim())));
    }

    console.log(maxZoneImbalance(loads, edges));
    rl.close();
});

C++

#include <bits/stdc++.h>
using namespace std;

class UnionFind {
private:
    vector<int> parent;

public:
    UnionFind(int n) {
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }

    int find(int x) {
        while (parent[x] != x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void unite(int a, int b) {
        int rootA = find(a);
        int rootB = find(b);

        if (rootA != rootB) {
            parent[rootB] = rootA;
        }
    }
};

int maxZoneImbalance(vector<int>& loads, vector<vector<int>>& edges) {
    int n = loads.size();

    if (edges.empty()) {
        return -1;
    }

    UnionFind uf(n);

    for (auto& edge : edges) {
        uf.unite(edge[0], edge[1]);
    }

    unordered_map<int, vector<int>> groups;
    for (int i = 0; i < n; i++) {
        int root = uf.find(i);
        groups[root].push_back(i);
    }

    int ans = -1;

    for (auto& item : groups) {
        vector<int>& nodes = item.second;

        if (nodes.size() < 2) {
            continue;
        }

        int maxLoad = INT_MIN;
        int minLoad = INT_MAX;

        for (int node : nodes) {
            maxLoad = max(maxLoad, loads[node]);
            minLoad = min(minLoad, loads[node]);
        }

        int imbalance = (maxLoad - minLoad) * nodes.size();
        ans = max(ans, imbalance);
    }

    return ans;
}

int main() {
    string line;
    getline(cin, line);

    vector<int> loads;
    vector<vector<int>> edges;

    int splitIndex = line.find("],");
    string loadsLine = line.substr(0, splitIndex + 1);
    string edgesLine = line.substr(splitIndex + 2);

    for (int i = 0; i < loadsLine.size(); i++) {
        if (isdigit(loadsLine[i])) {
            int num = 0;
            while (i < loadsLine.size() && isdigit(loadsLine[i])) {
                num = num * 10 + loadsLine[i] - '0';
                i++;
            }
            loads.push_back(num);
        }
    }

    if (edgesLine != "[]") {
        for (int i = 0; i < edgesLine.size(); i++) {
            if (isdigit(edgesLine[i])) {
                int a = 0;
                while (i < edgesLine.size() && isdigit(edgesLine[i])) {
                    a = a * 10 + edgesLine[i] - '0';
                    i++;
                }

                while (i < edgesLine.size() && !isdigit(edgesLine[i])) {
                    i++;
                }

                int b = 0;
                while (i < edgesLine.size() && isdigit(edgesLine[i])) {
                    b = b * 10 + edgesLine[i] - '0';
                    i++;
                }

                edges.push_back({a, b});
            }
        }
    }

    cout << maxZoneImbalance(loads, edges) << endl;

    return 0;
}

Go

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func maxZoneImbalance(loads []int, edges [][]int) int {
	n := len(loads)
	if len(edges) == 0 {
		return -1
	}
	parent := make([]int, n)
	for i := 0; i < n; i++ {
		parent[i] = i
	}
	var find func(int) int
	find = func(x int) int {
		for parent[x] != x {
			parent[x] = parent[parent[x]]
			x = parent[x]
		}
		return x
	}
	union := func(a, b int) {
		ra := find(a)
		rb := find(b)
		if ra != rb {
			parent[rb] = ra
		}
	}
	for _, e := range edges {
		union(e[0], e[1])
	}
	groups := make(map[int][]int)
	for i := 0; i < n; i++ {
		r := find(i)
		groups[r] = append(groups[r], i)
	}
	ans := -1
	for _, nodes := range groups {
		if len(nodes) < 2 {
			continue
		}
		maxLoad := -1 << 31
		minLoad := 1<<31 - 1
		for _, node := range nodes {
			if loads[node] > maxLoad {
				maxLoad = loads[node]
			}
			if loads[node] < minLoad {
				minLoad = loads[node]
			}
		}
		imbalance := (maxLoad - minLoad) * len(nodes)
		if imbalance > ans {
			ans = imbalance
		}
	}
	return ans
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	line, _ := reader.ReadString('\n')
	line = strings.TrimSpace(line)
	idx := strings.Index(line, "],")
	if idx == -1 {
		return
	}
	loadsPart := line[:idx+1]
	edgesPart := line[idx+2:]

	loadsStr := strings.Trim(loadsPart, "[]")
	loadTokens := strings.Split(loadsStr, ",")
	loads := make([]int, 0)
	for _, t := range loadTokens {
		t = strings.TrimSpace(t)
		if t == "" {
			continue
		}
		v, _ := strconv.Atoi(t)
		loads = append(loads, v)
	}

	var edges [][]int
	edgesPart = strings.TrimSpace(edgesPart)
	if edgesPart == "[]" {
		edges = [][]int{}
	} else {
		inner := strings.TrimPrefix(edgesPart, "[[")
		inner = strings.TrimSuffix(inner, "]]")
		pairs := strings.Split(inner, "],[")
		for _, p := range pairs {
			nums := strings.Split(p, ",")
			if len(nums) == 2 {
				a, _ := strconv.Atoi(strings.TrimSpace(nums[0]))
				b, _ := strconv.Atoi(strings.TrimSpace(nums[1]))
				edges = append(edges, []int{a, b})
			}
		}
	}

	fmt.Println(maxZoneImbalance(loads, edges))
}

C语言

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

int find(int* parent, int x) {
    while (parent[x] != x) {
        parent[x] = parent[parent[x]];
        x = parent[x];
    }
    return x;
}

void unionSet(int* parent, int a, int b) {
    int ra = find(parent, a);
    int rb = find(parent, b);
    if (ra != rb) parent[rb] = ra;
}

int maxZoneImbalance(int* loads, int n, int edges[][2], int m) {
    if (m == 0) return -1;
    int* parent = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) parent[i] = i;
    for (int i = 0; i < m; i++) {
        unionSet(parent, edges[i][0], edges[i][1]);
    }
    int* groupSize = (int*)calloc(n, sizeof(int));
    int* groupMin = (int*)malloc(n * sizeof(int));
    int* groupMax = (int*)malloc(n * sizeof(int));
    int ans = -1;
    for (int i = 0; i < n; i++) {
        int r = find(parent, i);
        if (groupSize[r] == 0) {
            groupMin[r] = groupMax[r] = loads[i];
        } else {
            if (loads[i] < groupMin[r]) groupMin[r] = loads[i];
            if (loads[i] > groupMax[r]) groupMax[r] = loads[i];
        }
        groupSize[r]++;
    }
    for (int i = 0; i < n; i++) {
        if (groupSize[i] >= 2) {
            int imbalance = (groupMax[i] - groupMin[i]) * groupSize[i];
            if (imbalance > ans) ans = imbalance;
        }
    }
    free(parent);
    free(groupSize);
    free(groupMin);
    free(groupMax);
    return ans;
}

int main() {
    char line[100000];
    scanf("%[^\n]", line);
    char* idx = strstr(line, "],");
    if (!idx) return 1;
    int splitPos = idx - line;
    char loadsPart[50000];
    strncpy(loadsPart, line, splitPos + 1);
    loadsPart[splitPos + 1] = '\0';
    char* edgesPart = line + splitPos + 2;

    int* loads = (int*)malloc(100000 * sizeof(int));
    int loadCount = 0;
    char* lp = loadsPart;
    while (*lp == '[') lp++;
    char* end = strchr(lp, ']');
    if (end) *end = '\0';
    char* token = strtok(lp, ",");
    while (token) {
        while (*token == ' ') token++;
        loads[loadCount++] = atoi(token);
        token = strtok(NULL, ",");
    }

    int edges[100000][2];
    int edgeCount = 0;
    while (*edgesPart == ' ') edgesPart++;
    if (strcmp(edgesPart, "[]") != 0) {
        char* ep = edgesPart;
        while (*ep == '[') ep++;
        char buff[100000];
        strcpy(buff, ep);
        int len = strlen(buff);
        if (len > 0 && buff[len - 1] == ']') buff[--len] = '\0';
        char* p = buff;
        while (*p) {
            char* next = strstr(p, "],[");
            if (next) {
                *next = '\0';
                int a, b;
                sscanf(p, "%d,%d", &a, &b);
                edges[edgeCount][0] = a;
                edges[edgeCount][1] = b;
                edgeCount++;
                p = next + 3;
            } else {
                int a, b;
                sscanf(p, "%d,%d", &a, &b);
                edges[edgeCount][0] = a;
                edges[edgeCount][1] = b;
                edgeCount++;
                break;
            }
        }
    }

    int result = maxZoneImbalance(loads, loadCount, edges, edgeCount);
    printf("%d\n", result);
    free(loads);
    return 0;
}

完整用例

用例1

[100,200,150,50,300],[[0,1],[1,2],[3,4]]

用例2

[80,90,80,90],[[0,1],[1,2],[2,3]]

用例3

[100,200,300],[]

用例4

[50,100,150],[[0,1]]

用例5

[10,20,30,40],[[0,1],[2,3]]

用例6

[1,1,1,1],[[0,1],[1,2],[2,3]]

用例7

[0,1000],[[0,1]]

用例8

[10,20,30,40,50],[[0,1],[1,2],[2,3],[3,4]]

用例9

[5,5],[[0,1]]

用例10

[100],[]

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值