单源最短路(Bellman - Ford算法)

本文探讨了在牛群中寻找与所有成员平均距离最短的个体问题,通过电影合作网络构建图模型,运用Dijkstra算法计算最短路径,旨在找到社交网络中最具连接性的节点。
题目描述(POJ2139)

牛们最近在拍电影,所以他们准备去玩一个游戏——“六度分割”的变体。 游戏是这样进行的:每个牛离自己的距离是0度,如果两个不同的牛同时出现在一个电影里,那么他们之间的距离为1度,如果两只牛从未一起工作,但它们都与第三只牛一起工作,那么他们之间的距离为2度。 这N(2<=N<=300)头牛对找出那只牛与所有牛之间的平均距离最短感兴趣。当然,不算上他自己。这些牛拍了M(1<=M<=10000)部电影,并且保证每两个牛之间都有一定的关系。求那一头牛与其它牛距离的平均值最小值,把它乘100输出。

可以这么理解,如果A和B是一个集合里的,AB之间的距离为1
如果B和C是一个集合里的,AC之间的距离为2
自己与自己的距离为1

代码实现

定义一个类,n1到n2的距离为cast

class E{
	int n1, n2, cast;
}

储存数据,将所有的集合储存起来

		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		int m = sc.nextInt();
		E [] e = new E[100000];
		int index = 0;
		
		for(int i = 0; i < m; i++){
			
			int num = sc.nextInt();
			int [] team = new int [num];
			
			for(int j = 0; j < num; j++){
				team[j] = sc.nextInt();
			}
			
			for(int j = 0; j < num - 1; j++){
				for(int k = j + 1; k < num; k++){
					E ee = new E();
					ee.n1 = team[j];
					ee.n2 = team[k];
					ee.cast = 1;
					
					e[index++] = ee;
					
			}

处理每一条边

		int result = Integer.MAX_VALUE;
		
		for(int i = 1; i <= n; i++){
			int [] d = new int [n + 1];
			
			for(int j = 1; j <= n; j++){
				d[j] = Integer.MAX_VALUE;
			}
			
			d[i] = 0;
			
			while(true){
				
				boolean update = false;
				
				for(int j = 0; j < e.length; j++){
					if(e[j] == null) break;
					
					if(d[e[j].n1] != Integer.MAX_VALUE){
						if(d[e[j].n2] > d[e[j].n1] + e[j].cast){
							d[e[j].n2] = d[e[j].n1] + e[j].cast;
							update = true;
						}
					}
					
					if(d[e[j].n2] != Integer.MAX_VALUE){
						if(d[e[j].n1] > d[e[j].n2] + e[j].cast){
							d[e[j].n1] = d[e[j].n2] + e[j].cast;
							update = true;
						}
					}
					
				}
				
				if(!update) break;
			}
			
			for(int j = 1; j <= n; j++){
				d[0] += d[j];
			}
			
			if(d[0] * 100 < result && d[0] != 0){
				result = d[0] * 100;
			}
		}
		
		System.out.println(result / (n - 1));
### Bellman-Ford算法单源短路问题的实现与分析 Bellman-Ford算法是一种用于解决单源短路径问题的经典算法,能够处理带负权边的图。该算法的核心思想是通过松弛操作逐步更新从点到其他所有顶点的距离,直到达到优解。以下是关于Bellman-Ford算法的具体实现和分析[^1]。 #### 算法原理 Bellman-Ford算法的基本原理是基于动态规划的思想。它通过多执行 \(n-1\) 次松弛操作(其中 \(n\) 是图中顶点的数量),确保从点到所有顶点的短路径被正确计算。每次松弛操作都会遍历图中的所有边,并尝试更新当前已知的短路径距离。如果在第 \(n-1\) 次迭代后仍然可以更新某些顶点的距离,则说明图中存在负权环[^2]。 #### 算法实现 以下是Bellman-Ford算法的伪代码及其实现: ```python def bellman_ford(graph, source): # 初始化距离数组,将所有顶点的距离设为无穷大,点距离设为0 distance = {node: float('inf') for node in graph} distance[source] = 0 # 图中顶点数 n = len(graph) # 进行n-1次松弛操作 for _ in range(n - 1): for u in graph: for v, weight in graph[u]: if distance[u] + weight < distance[v]: distance[v] = distance[u] + weight # 检查是否存在负权环 for u in graph: for v, weight in graph[u]: if distance[u] + weight < distance[v]: raise ValueError("Graph contains a negative-weight cycle") return distance ``` #### 陈越与浙江大学的相关研究 陈越教授及其团队在浙江大学讲授的数据结构与算法课程中,对Bellman-Ford算法进行了深入讲解。课程中强调了Bellman-Ford算法的优势在于能够处理带有负权边的图,但其时间复杂度较高,为 \(O(n \cdot m)\),其中 \(n\) 是顶点数,\(m\) 是边数。因此,在实际应用中,若图中不存在负权边,通常会优先选择Dijkstra算法以提高效率。 此外,陈越教授还提到了Bellman-Ford算法的一种优化方法——队列优化(SPFA算法)。该方法通过维护一个队列来减少不必要的松弛操作次数,从而在大多数情况下显著提升性能[^2]。 #### 算法分析 Bellman-Ford算法的时间复杂度为 \(O(n \cdot m)\),空间复杂度为 \(O(n)\)。尽管其时间复杂度较高,但它具有以下优势: 1. 能够处理带负权边的图。 2. 可以检测图中是否存在负权环。 然而,对于大规模稀疏图,Bellman-Ford算法可能显得效率较低。此时,可以考虑使用Dijkstra算法或其变种(如堆优化版)[^1]。 #### 示例应用 以下是一个具体的例子,展示如何使用Bellman-Ford算法求解单源短路径问题。 假设图的邻接表表示如下: ```python graph = { 'A': [('B', 1), ('C', 4)], 'B': [('C', 2), ('D', 6)], 'C': [('D', 3)], 'D': [] } ``` 调用 `bellman_ford(graph, 'A')` 将返回从顶点 `'A'` 到其他所有顶点的短路径距离。 #### 注意事项 在实际应用中,需要特别注意图中是否存在负权环。若存在负权环,则无法计算出有效的短路径。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值