最短路径Floyd算法-POJ1847Tram

定义  Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。

核心思路

  通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

  从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

  采用的是松弛技术,对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);

  其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}

  map[i,j]表示i到j的最短距离

  K是穷举i,j的断点

  map[n,n]初值应该为0,或者按照题目意思来做。

  当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路

算法过程

  把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=空值。

  定义一个矩阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。

  把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。

  在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。

  比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。

时间复杂度

  O(n^3)

优缺点分析

  Floyd算法适用于APSP(All Pairs Shortest Paths),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。

  优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单;

  缺点:时间复杂度比较高,不适合计算大量数据。

算法实现

  c语言:

  #include<fstream>

  #define Maxm 501

  using namespace std;

  ifstream fin("APSP.in");

  ofstream fout("APSP.out");

  int p,q,k,m;

  int Vertex,Line[Maxm];

  int Path[Maxm][Maxm],Map[Maxm][Maxm],Dist[Maxm][Maxm];

  void Root(int p,int q)

  {

  if (Path[p][q]>0)

  {

  Root(p,Path[p][q]);

  Root(Path[p][q],q);

  }

  else

  {

  Line[k]=q;

  k++;

  }

  }

  int main()

  {

  memset(Path,0,sizeof(Path));

  memset(Map,0,sizeof(Map));

  memset(Dist,0,sizeof(Dist));

  fin >> Vertex;

  for(p=1;p<=Vertex;p++)

  for(q=1;q<=Vertex;q++)

  {

  fin >> Map[p][q];

  Dist[p][q]=Map[p][q];

  }

  for(k=1;k<=Vertex;k++)

  for(p=1;p<=Vertex;p++)

  if (Dist[p][k]>0)

  for(q=1;q<=Vertex;q++)

  if (Dist[k][q]>0)

  {

  if (((Dist[p][q]>Dist[p][k]+Dist[k][q])||(Dist[p][q]==0))&&(p!=q))

  {

  Dist[p][q]=Dist[p][k]+Dist[k][q];

  Path[p][q]=k;

  }

  }

  for(p=1;p<=Vertex;p++)

  {

  for(q=p+1;q<=Vertex;q++)

  {

  fout << "/n==========================/n";

  fout << "Source:" << p << '/n' << "Target " << q << '/n';

  fout << "Distance:" << Dist[p][q] << '/n';

  fout << "Path:" << p;

  k=2;

  Root(p,q);

  for(m=2;m<=k-1;m++)

  fout << "-->" << Line[m];

  fout << '/n';

  fout << "==========================/n";

  }

  }

  fin.close();

  fout.close();

  return 0;

  }

  注解:无法连通的两个点之间距离为0;
  Sample Input
  7
  00 20 50 30 00 00 00
  20 00 25 00 00 70 00
  50 25 00 40 25 50 00
  30 00 40 00 55 00 00
  00 00 25 55 00 10 70
  00 70 50 00 10 00 50
  00 00 00 00 70 50 00
  Sample Output
  ==========================
  Source:1
  Target 2
  Distance:20
  Path:1-->2
  ==========================
  ==========================
  Source:1
  Target 3
  Distance:45
  Path:1-->2-->3
  ==========================
  ==========================
  Source:1
  Target 4
  Distance:30
  Path:1-->4
  ==========================
  ==========================
  Source:1
  Target 5
  Distance:70
  Path:1-->2-->3-->5
  ==========================
  ==========================
  Source:1
  Target 6
  Distance:80
  Path:1-->2-->3-->5-->6
  ==========================
  ==========================
  Source:1
  Target 7
  Distance:130
  Path:1-->2-->3-->5-->6-->7
  ==========================
  ==========================
  Source:2
  Target 3
  Distance:25
  Path:2-->3
  ==========================
  ==========================
  Source:2
  Target 4
  Distance:50
  Path:2-->1-->4
  ==========================
  ==========================
  Source:2
  Target 5
  Distance:50
  Path:2-->3-->5
  ==========================
  ==========================
  Source:2
  Target 6
  Distance:60
  Path:2-->3-->5-->6
  ==========================
  ==========================
  Source:2
  Target 7
  Distance:110
  Path:2-->3-->5-->6-->7
  ==========================
  ==========================
  Source:3
  Target 4
  Distance:40
  Path:3-->4
  ==========================
  ==========================
  Source:3
  Target 5
  Distance:25
  Path:3-->5
  ==========================
  ==========================
  Source:3
  Target 6
  Distance:35
  Path:3-->5-->6
  ==========================
  ==========================
  Source:3
  Target 7
  Distance:85
  Path:3-->5-->6-->7
  ==========================
  ==========================
  Source:4
  Target 5
  Distance:55
  Path:4-->5
  ==========================
  ==========================
  Source:4
  Target 6
  Distance:65
  Path:4-->5-->6
  ==========================
  ==========================
  Source:4
  Target 7
  Distance:115
  Path:4-->5-->6-->7
  ==========================
  ==========================
  Source:5
  Target 6
  Distance:10
  Path:5-->6
  ==========================
  ==========================
  Source:5
  Target 7
  Distance:60
  Path:5-->6-->7
  ==========================
  ==========================
  Source:6
  Target 7
  Distance:50
  Path:6-->7
  ==========================
  Matlab源代码为

  function [D,R]=floyd(a)

  n=size(a,1);
  D=a
  for i=1:n
  for j=1:n
  R(i,j)=j;
  end
  end
  R

  for k=1:n
  for i=1:n
  for j=1:n
  if D(i,k)+D(k,j)<D(i,j)
  D(i,j)=D(i,k)+D(k,j);
  R(i,j)=R(i,k);
  end
  end
  end
  k
  D
  R
  end

  在M文件中建立
  

  pascal语言:

  program floyd;

  var

  st,en,f:integer;

  n,i,j,x:integer;

  a:array[1..10,1..10]of integer;

  path,map1,map2:array[1..10,1..10]of integer;

  begin

  readln(n);

  for i:=1 to n do

  begin

  for j:=1 to n do

  begin

  read(a[i,j]);

  path[i,j]:=j;

  end;

  readln;

  end;

  for x:=1 to n do

  for i:=1 to n do

  for j:=1 to n do

  if a[i,j]>a[i,x]+a[x,j] then

  begin

  a[i,j]:=a[i,x]+a[x,j];

  path[i,j]:=path[i,x];

  end;

  readln(st,en);

  writeln(a[st,en]);

  writeln;

  f:=st;

  while f<> en do

  begin

  write(f);

  write('-->');

  f:=path[f,en];

  end;

  write(en);

  end.
POJ1847

Tram
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 3700   Accepted: 1321

Description

Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch.

When a driver has do drive from intersection A to the intersection B he/she tries to choose the route that will minimize the number of times he/she will have to change the switches manually.

Write a program that will calculate the minimal number of switch changes necessary to travel from intersection A to intersection B.

Input

The first line of the input contains integers N, A and B, separated by a single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is the number of intersections in the network, and intersections are numbered from 1 to N.

Each of the following N lines contain a sequence of integers separated by a single blank character. First number in the i-th line, Ki (0 <= Ki <= N-1), represents the number of rails going out of the i-th intersection. Next Ki numbers represents the intersections directly connected to the i-th intersection.Switch in the i-th intersection is initially pointing in the direction of the first intersection listed.

Output

The first and only line of the output should contain the target minimal number. If there is no route from A to B the line should contain the integer "-1".

Sample Input

3 2 1
2 2 3
2 3 1
2 1 2

Sample Output

0

Source

Croatia OI 2002 Regional - Juniors
#include<stdio.h> int main() { int i,j,k,m,n,a,b,s,dis[120][120]; scanf("%d%d%d",&n,&a,&b); for(i=1;i<=n;i++) for(j=1;j<=n;j++) dis[i][j]=999999; for(i=1;i<=n;i++) dis[i][i]=0; for(i=1;i<=n;i++) { scanf("%d",&m); for(j=0;j<m;j++) { scanf("%d",&s); if(j==0) dis[i][s]=0; else dis[i][s]=1; } } for(i=1;i<=n;i++) for(j=1;j<=n;j++) for(k=1;k<=n;k++) if(dis[j][k]>dis[j][i]+dis[i][k]) dis[j][k]=dis[j][i]+dis[i][k]; if(dis[a][b]==999999) puts("-1"); else printf("%d/n",dis[a][b]); }

 

你可能感兴趣的:(算法,Integer,Path,Rails,output,distance)