在一个图中,若从一个结点到另一个结点存在着路径,定义路径长度为一条路径上所经过的边的权值之和。从一个结点到令一个结点可能存在着多条路径,路径最短的那条称作最短路径。
Dijkastra思想(不能包含负权值的边):
设置两个结点集合S和T,S中存放已找到最短路径的结点,T中存放当前还未找到最短路径的结点。初始状态S中只包含起始点u0。然后不断的从集合T中选择到u0路径长度最短的结点v,每次加入,都要修改从源点u0到集合T中剩余结点的当前最短路径长度,为原来路径长度与u0经过v到达该结点的路径长度中的较小者。当T为空,算法结束。
Dijkastra设计:
distance数组用来记录从源点到其余个点的当前最短距离数值。
#include <iostream>
using namespace std;
const int MAX = 200000000;
int n; //物品总数
int m; //等级差距*
int graph[101][101]; //图
int d[101]; //从开始点到其余个点的花费
int value[101]; //物品本身的价值*
int level[101]; //物品等级*
bool s[101],in_limit[101]; //标记数组*
int dijkastra()
{
int result = MAX;
int i,j;
int k,dis;
memset(s,0,sizeof(s));
for(i = 2,d[1] = 0; i <= n; i++)
d[i] = MAX;
for(i = 1; i <= n; i++)
{
k = 0;
dis = MAX;
for(j = 1; j <= n; j++)
if(!s[j] && d[j] <= dis && in_limit[j])
{
k = j;
dis = d[j];
}
s[k] = 1;
for(j = 1; j <= n; j++)
{
if(in_limit[j] && d[j] > d[k] + graph[k][j])
d[j] = d[k] + graph[k][j];
}
}
for(i = 1; i <= n; i++)
{
d[i] += value[i];
if(d[i] < result)
result = d[i];
}
return result;
}
int main()
{
int i,j;
int result = MAX,t = 0;
int t1,v1;
int x;
cin>>m>>n;
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(i == j)
graph[i][j] = 0;
else
graph[i][j] = MAX;
for(i = 1; i <= n; i++)
{
cin>>value[i]>>level[i]>>x;
for(j = 1; j <= x; j++)
{
cin>>t1>>v1;
graph[i][t1] = v1;
}
}
for(i = 0; i <= m; i++)
{
memset(in_limit,0,sizeof(in_limit));
for(j = 1; j <= n; j++)
if(level[j] >= level[1]-m+i && level[j] <= level[1]+i)
in_limit[j] = 1;
t = dijkastra();
if(result > t)
result = t;
}
cout<<result<<endl;
return 0;
}
上述迪杰斯特拉算法可以求出某个结点与其他结点的最短路径,现在考虑这样一个问题:求出图中每对顶点的最短路径。用简单的方法,把每个顶点作为源点,用迪杰斯特拉,可以求出每对结点的最短路径。其实还有更简单的方法——弗洛伊德算法。(代码简单,思维复杂)
folyd思想(动归,可以包含负权值的边,但不能有负环):
将图G中顶点编号,从1到n。现在考虑从i到j的最短路径,若k是这条路上的中间结点,那么由i到k和由k到j的这两条子路径应分别是由i到k和由k到j的最短路径。否则,这条由i到j的路径就不是具有最小长度的路径。于是,最优性原理成立,这表明有使用动态规划的可能性。如果k是编号最高的中间结点,那么由i到k的这条路径上就不会有比k-1更大的结点通过。同样,由k到j路径上也不会有比k-1更大的结点通过。因此,可以把求取一条由i到j的最短路径看成如下过程:首先需要决策哪一个结点是该路径上具有最大编号的中间结点k,然后就再去求由i到k和由k到j这两对结点间的最短路径。当然,这两条路径都不可能有比k-1还大的中间结点。
则得到递推式:
A(i,j)k = min{A(i,j)k-1 , A(i,k)k-1 + A(k,j)k-1)}, k>=1
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
public static int MAX = 991;
public static int[][] map = new int[101][101];
public static int n;
public static void floyd() {
int i, j, k;
for (k = 1; k <= n; k++) {
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (i != k && j != k) {
if (map[i][k] + map[k][j] < map[i][j])
map[i][j] = map[i][k] + map[k][j];
}
}
}
}
}
public static void initial() {
int i, j;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
map[i][j] = MAX;
}
public static void main(String[] args) {
int i,j,t,a;
int result1,result2;
boolean flag = false;
Scanner cin = new Scanner(new BufferedInputStream(System.in));
while((n = cin.nextInt()) != 0) {
result1 = 0;
result2 = MAX;
initial();
for(i = 1;i <= n; i++) {
t = cin.nextInt();
for (j = 1; j <= t; j++) {
a = cin.nextInt();
map[i][a] = cin.nextInt();
}
}
floyd();
flag = false;
for (i = 1; i <= n; i++) {
t = 0;
for (j = 1; j <= n; j++) {
if (i != j) {
if (map[i][j] == MAX) {
t = 0;
break;
}
if (map[i][j] > t)
t = map[i][j];
}
}
if (t != 0) {
flag = true;
if (t < result2) {
result1 = i;
result2 = t;
}
}
}
if(!flag)
System.out.println("disjoint");
else
System.out.println(result1 + " " +result2);
}
}
}
参见poj1062,1125
分享到:
相关推荐
贪心算法解决单源最短路径问题的基本思想是分步求出最短路径,每一步产生一个到达新目的顶点的最短路径。下一步所能达到的目的顶点通过贪婪准则选取,即选择路径最短的目的顶点。设置顶点集合S,并不断作贪心选择来...
在【描述】中提到的实验报告是针对计算机科学与技术专业学生的,旨在通过实践加深对单源最短路径算法的理解。实验中特别提到了贪心算法,这是一种解决问题的策略,它在每一步选择局部最优解,希望通过一系列局部最优...
单源最短路径问题是从一个指定的起点到图中所有其他顶点的最短路径问题,这个问题在图论和计算机科学中有广泛的应用,例如网络路由优化、物流配送路线规划等。 分支限界法通常包括以下几个关键组件: 1. **搜索...
"单源最短路径--分支限界法" 单源最短路径是图论中的一种常见问题,它是指从一个源顶点到所有其他顶点的最短路径长度。这里的长度是指路上各边权之和。本文将介绍一种解决单源最短路径问题的方法,即分支限界法。 ...
迪杰斯特拉(Dijkstra)算法是一种用于寻找有向图中单源最短路径的经典算法,由荷兰计算机科学家艾兹格·迪杰斯特拉在1956年提出。在这个算法中,我们从一个源节点开始,逐步扩展最短路径到其他节点,直到到达所有...
单源最短路径问题在图论中是一个经典问题,它要求找出从图中一个特定顶点(源点)到其他所有顶点的最短路径。在这个场景中,我们使用了分支限界法来解决这个问题。分支限界法是一种搜索算法,通常用于优化问题,它...
代码中使用了一个最小堆(`LinkedList`)来维护待扩展的顶点,并利用`compareTo`方法对堆中的元素进行排序,以确保每次取出的是路径长度最短的顶点进行扩展。 具体来说: 1. **数据结构**: 定义了`Heapnode`类来存储...
经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径经典算法单源最短路径
单源最短路径C语言实现,简单易懂,适合算法学习
实验目的:理解贪心法的核心思想、贪心法的求解过程,并从算法分析与设计的角度,对单源最短路径问题的 Dijkstra 算法求解有进一步理解。 实验内容: 1. 问题描述:给定一个有向带权图 G=(V,E),其中每条边的权是...
例如,可以将Dijkstra算法与Floyd-Warshall算法结合使用,以解决所有对最短路径问题。 在实验中,我们使用VC6.0实现了Dijkstra算法,并将其应用于实际问题中。在实验过程中,我们首先构造了有向图的邻接矩阵,然后...
在 main 函数中,我们首先输入图的结点个数和每条边的权值,然后我们使用贪心算法来计算从源点到每个点的最短路径的长度和前一个点。最后,我们输出从源点到每个点的最短路径的长度和前一个点。 单源点最短路径问题...
单源最短路径的分支限界算法 单源最短路径是图论中一个基本的问题,旨在寻找从某一个起始点(源点)到图中所有其他顶点的最短路径。分支限界算法是一种常用的解决单源最短路径问题的方法,本文档介绍了使用 C++ ...
### 单源最短路径算法解析与应用实例 在图论和网络理论中,寻找从一个顶点到图中其他所有顶点的最短路径是一个常见的问题,这被称为单源最短路径问题。该问题在各种领域都有广泛的应用,如交通规划、网络路由选择、...
单源最短路径分支界限法 单源最短路径分支界限法是指在图论中,使用分支限界法来解决单源最短路径问题的算法。该算法采用java语言实现,参考了算法设计与分析的方法。 单源最短路径问题是指在一个有权重的图中,找...
算法设计与分析课内实验——动态规划求单源最短路径。文档很齐全,包括算法分析过程和源代码(java语言eclipse环境)
算法设计与分析实验报告,附已通过源码,供学习参考,共勉♪ 目录摘要如下: 1.问题描述 2.实验目的 3.实验原理 4.实验设计 (包括输入格式、算法、输出格式) 5.实验结果与分析 (除了截图外,实验结果还用...
通过对给定代码的理解和分析,我们可以清楚地了解到贪心算法解决单源最短路径问题的基本思路和实现过程。这种方法简单直观,易于理解,但在某些特定条件下可能存在一定的局限性。因此,在实际应用中需要根据具体情况...
单源最短路径问题在图论中是一个经典问题,它旨在找出从图中一个特定顶点(源点)到其他所有顶点的最短路径。在这个场景中,我们提到的"单源最短路径vc源码"是用C++编程语言实现的一个贪心算法解决方案,该算法在...
关于单源最短路径的问题非常典型,这里没有给出分析与证明,仅仅给出了实现。 需要指出的是,许多实现仅给出了最短路径的长度,而没有给出“最短路径”,这里用给出了实现。 如程序中那样,定义一个数组p[N],其中...