最长广播响应
2025华为OD机试 - 华为OD上机考试 200分题型
华为OD机试真题目录点击查看: 华为OD机试真题题库目录|机考题库 + 算法考点详解
题目描述
某通信网络中有N个网络结点,用1到N进行标识。
网络中的结点互联互通,且结点之间的消息传递有时延,相连结点的时延均为一个时间单位。
现给定网络结点的连接关系link[i]={u,v},其中u和v表示网络结点。
当指定一个结点向其他结点进行广播,所有被广播结点收到消息后都会在原路径上回复一条响应消息,请计算发送结点至少需要等待几个时间单位才能收到所有被广播结点的响应消息。
备注:
- N的取值范围为[1,100];
- 连接关系link的长度不超过3000,且1 <= u,v <= N;
- 网络中任意结点间均是可达的;
输入描述
输入的第一行为两个正整数,分别表示网络结点的个数N,以及时延列表的长度T;
接下来的T行输入,表示结点间的连接关系列表;
最后一行的输入为一个正整数,表示指定的广播结点序号;
输出描述
输出一个整数,表示发送结点接收到所有响应消息至少需要等待的时长。
用例1
输入
none
5 7
1 4
2 1
2 3
2 4
3 4
3 5
4 5
2
输出
none
4
说明
结点2到5的最小时延为2,到剩余结点的最小时延均为1,所以至少要等待2*2=4s。
题解
思路: 最短路算法
- 输出最少需要多少时间才能接受到全部节点的响应这句话可以理解为从点u到达所有点的最短距离的最大值 * 2
- 这道题就可以转换成求点单点最短路。可以是使用经典的dijkstra(迪杰斯特拉)来解决。可以去详细学学这个算法,简单说一些迪杰斯特拉算法的思路:
- 算法的本质是贪心算法,使用当前找到的最短距离去更新与之相邻的点的距离.
- 假设当前点u距离为最小值,更新与之相邻的点离启动的距离,状态转移方程为 当(dist[u] + w < dist[v])时, dist[v] = dis[u] + w。
- 遍历起点到所有点的距离找出其中最大值 * 2就是结果。
c++
c++
#include <functional>
#include<iostream>
#include<vector>
#include<string>
#include <utility>
#include <sstream>
#include<algorithm>
#include <limits>
#include<queue>
using namespace std;
const int INF = numeric_limits<int>::max();
// 迪杰斯特拉求最短路径
int dijkstra(int start, const vector<vector<int>>& graph) {
int n = graph.size();
vector<int> dist(n, INF);
dist[start] = 0;
// 优先队列(最小堆,小的优先级高)
priority_queue<pair<int,int>, vector<pair<int, int>>, greater<>> pq;
pq.push({0, start});
while (!pq.empty()) {
auto [d,u] = pq.top();
pq.pop();
if (d > dist[u]) {
continue;
}
// 更新与点u相连的点
for (const auto& v : graph[u]) {
if (dist[u] + 1 < dist[v]) {
dist[v] = dist[u] + 1;
pq.push({dist[v], v});
}
}
}
// 单向最长时延
int res = 0;
for (int i =0; i < n; i++) {
if (dist[i] == INF) {
res = -1;
break;
}
res = max(res, dist[i]);
}
return res;
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> g(n);
while (m--) {
int x, y;
cin >> x >> y;
g[x-1].push_back(y-1);
g[y-1].push_back(x-1);
}
int pos;
cin >> pos;
int res = dijkstra(pos-1, g);
// 往返 * 2
cout << res * 2;
return 0;
}
JAVA
JAVA
import java.io.*;
import java.util.*;
/**
* 迪杰斯特拉算法求最短路径
*/
public class Main {
static final int INF = Integer.MAX_VALUE;
static int dijkstra(int start, List<List<Integer>> graph) {
int n = graph.size();
int[] dist = new int[n];
Arrays.fill(dist, INF);
dist[start] = 0;
// 优先队列(最小堆,距离小的优先)
PriorityQueue<int[]> pq = new PriorityQueue<>(
(a, b) -> Integer.compare(a[0], b[0])
);
pq.offer(new int[]{0, start});
while (!pq.isEmpty()) {
int[] cur = pq.poll();
int d = cur[0], u = cur[1];
if (d > dist[u]) continue;
// 更新与 u 相连的点
for (int v : graph.get(u)) {
if (dist[u] + 1 < dist[v]) {
dist[v] = dist[u] + 1;
pq.offer(new int[]{dist[v], v});
}
}
}
// 单向最长时延
int res = 0;
for (int i = 0; i < n; i++) {
if (dist[i] == INF) return -1;
res = Math.max(res, dist[i]);
}
return res;
}
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i < n; i++) g.add(new ArrayList<>());
while (m-- > 0) {
int x = sc.nextInt();
int y = sc.nextInt();
g.get(x - 1).add(y - 1);
g.get(y - 1).add(x - 1);
}
int pos = sc.nextInt();
int res = dijkstra(pos - 1, g);
// 往返 * 2
System.out.println(res * 2);
}
}
Python
python
import sys
import heapq
INF = 10**18
# 迪杰斯特拉求最短路径
def dijkstra(start, graph):
n = len(graph)
dist = [INF] * n
dist[start] = 0
# 最小堆(距离小的优先)
pq = [(0, start)]
while pq:
d, u = heapq.heappop(pq)
if d > dist[u]:
continue
# 更新与 u 相连的点
for v in graph[u]:
if dist[u] + 1 < dist[v]:
dist[v] = dist[u] + 1
heapq.heappush(pq, (dist[v], v))
# 单向最长时延
res = 0
for d in dist:
if d == INF:
return -1
res = max(res, d)
return res
def main():
data = list(map(int, sys.stdin.read().split()))
idx = 0
n, m = data[idx], data[idx + 1]
idx += 2
g = [[] for _ in range(n)]
for _ in range(m):
x, y = data[idx], data[idx + 1]
idx += 2
g[x - 1].append(y - 1)
g[y - 1].append(x - 1)
pos = data[idx]
res = dijkstra(pos - 1, g)
# 往返 * 2
print(res * 2)
if __name__ == "__main__":
main()
JavaScript
js
const readline = require('readline');
// 最小堆实现
class MinHeap {
constructor() {
this.heap = [];
}
push(item) {
this.heap.push(item);
this._up(this.heap.length - 1);
}
pop() {
const top = this.heap[0];
const last = this.heap.pop();
if (this.heap.length > 0) {
this.heap[0] = last;
this._down(0);
}
return top;
}
isEmpty() {
return this.heap.length === 0;
}
_up(i) {
while (i > 0) {
let p = (i - 1) >> 1;
if (this.heap[p][0] <= this.heap[i][0]) break;
[this.heap[p], this.heap[i]] = [this.heap[i], this.heap[p]];
i = p;
}
}
_down(i) {
const n = this.heap.length;
while (true) {
let l = i * 2 + 1;
let r = i * 2 + 2;
let min = i;
if (l < n && this.heap[l][0] < this.heap[min][0]) min = l;
if (r < n && this.heap[r][0] < this.heap[min][0]) min = r;
if (min === i) break;
[this.heap[i], this.heap[min]] = [this.heap[min], this.heap[i]];
i = min;
}
}
}
// 迪杰斯特拉求最短路径(无权图,边权=1)
function dijkstra(start, graph) {
const n = graph.length;
const INF = 1e18;
const dist = Array(n).fill(INF);
dist[start] = 0;
// 优先队列(最小堆,距离小的优先)
const pq = new MinHeap();
pq.push([0, start]);
while (!pq.isEmpty()) {
const [d, u] = pq.pop();
if (d > dist[u]) continue;
// 更新与点 u 相连的点
for (const v of graph[u]) {
if (dist[u] + 1 < dist[v]) {
dist[v] = dist[u] + 1;
pq.push([dist[v], v]);
}
}
}
// 单向最长时延
let res = 0;
for (const d of dist) {
if (d === INF) return -1;
res = Math.max(res, d);
}
return res;
}
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const input = [];
rl.on('line', line => {
input.push(line.trim());
});
rl.on('close', () => {
// 按空白切分成数字
const data = input.join(' ').split(/\s+/).map(Number);
let idx = 0;
const n = data[idx++];
const m = data[idx++];
const g = Array.from({ length: n }, () => []);
for (let i = 0; i < m; i++) {
const x = data[idx++];
const y = data[idx++];
g[x - 1].push(y - 1);
g[y - 1].push(x - 1);
}
const pos = data[idx++];
const res = dijkstra(pos - 1, g);
// 往返 * 2
console.log(res * 2);
});
Go
go
package main
import (
"bufio"
"container/heap"
"fmt"
"os"
)
const INF = int(1e9)
// 优先队列节点
type Node struct {
dist int
u int
}
// 最小堆
type PriorityQueue []Node
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool { return pq[i].dist < pq[j].dist }
func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] }
func (pq *PriorityQueue) Push(x interface{}) {
*pq = append(*pq, x.(Node))
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
x := old[n-1]
*pq = old[:n-1]
return x
}
// 迪杰斯特拉求最短路径
func dijkstra(start int, graph [][]int) int {
n := len(graph)
dist := make([]int, n)
for i := 0; i < n; i++ {
dist[i] = INF
}
dist[start] = 0
pq := &PriorityQueue{}
heap.Init(pq)
heap.Push(pq, Node{0, start})
for pq.Len() > 0 {
cur := heap.Pop(pq).(Node)
d, u := cur.dist, cur.u
if d > dist[u] {
continue
}
// 更新与 u 相连的点
for _, v := range graph[u] {
if dist[u]+1 < dist[v] {
dist[v] = dist[u] + 1
heap.Push(pq, Node{dist[v], v})
}
}
}
// 单向最长时延
res := 0
for i := 0; i < n; i++ {
if dist[i] == INF {
return -1
}
if dist[i] > res {
res = dist[i]
}
}
return res
}
func main() {
in := bufio.NewReader(os.Stdin)
var n, m int
fmt.Fscan(in, &n, &m)
g := make([][]int, n)
for i := 0; i < m; i++ {
var x, y int
fmt.Fscan(in, &x, &y)
g[x-1] = append(g[x-1], y-1)
g[y-1] = append(g[y-1], x-1)
}
var pos int
fmt.Fscan(in, &pos)
res := dijkstra(pos-1, g)
// 往返 * 2
fmt.Println(res * 2)
}