弗洛伊德算法

图片 1

Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。

样例可以通过,但是提交后显示运行超时使用scanner作为输入使用了队列用来储存数据其他的只使用了基本的for循环和数组CCF答题语言选了个JAVA求各位大佬帮帮孩子尝试过使用BufferReader代替scanner但是还是超时,也再百度上查询过其他方法尝试解决,但是都未成功代码:publicclassMain{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubScannerinput=newScanner(System.in);intm,n;//m类初始状态每类中有n个m=input.nextInt();n=input.nextInt();things[]things=newthings[m];for(inti=0;im;i++){things[i]=newthings();}for(inti=0;in;i++){inta,b;a=input.nextInt();b=input.nextInt();thingc=newthing(a,b);for(intj=0;jm;j++){things[j].add(c);}}intr=input.nextInt();//操作的次数intk=-1;//用来计算查询操作的次数Queueint[]queue=newLinkedListint[]();for(inti=0;ir;i++){inta=input.nextInt();//选择操作if(a==1){//增加操作intb,id,score;//要加入的商的所属类、商品编号、得分b=input.nextInt();id=input.nextInt();score=input.nextInt();thingthing=newthing(id,score);things[b].add(thing);}elseif(a==2){intb,id;//要删除的商品的所属类、编号b=input.nextInt();id=input.nextInt();things[b].del(id);}elseif(a==3){//查找操作k++;intmax=input.nextInt();intmmax=0;int[]cm=newint[m];for(intj=0;jm;j++){cm[j]=input.nextInt();//用来记录每个类中要查询的个数}for(intj=0;jm;j++){mmax+=cm[j];}if(max=mmax){for(intj=0;jm;j++){int[]b=newint[cm[j]];b=things[j].findmax(cm[j]);queue.add(b);}}else{into=0;for(intj=0;jm;j++){if(o==max){o–;int[]b=newint[cm[j]];for(intq=0;qcm[j];q++){b[q]=-1;}queue.add(b);}else{int[]b=newint[cm[j]];b=things[j].findmax(cm[j]);queue.add(b);}o++;}}}}for(inti=0;i(k+1)*2;i++){int[]print=queue.poll();for(intj=0;jprint.length;j++){System.out.print(print[j]+””);}System.out.println();}//for(inti=0;im;i++){//things[i].show();//}}}classthing{intid;intscore;publicthing(intid,intscore){this.id=id;this.score=score;}}classthings{Queuethingqueue=newLinkedListthing();intn;publicthings(){//TODOAuto-generatedconstructorstub}publicvoidadd(thinga){queue.add(a);}voiddel(intid){for(inti=0;iqueue.size();i++){thinga=queue.poll();if(a.id==id){break;}else{queue.add(a);}}}int[]findmax(intnum){intmax[]=newint[num];int[]p=newint[queue.size()];for(inti=0;iqueue.size();i++){//将得分传入一个数组thinga=queue.poll();p[i]=a.score;queue.add(a);}for(inti=0;iqueue.size()-1;i++){//使用冒泡排序将得分进行排序for(intj=0;jqueue.size()-i-1;j++){if(p[j]p[j+1]){inttemp=p[j];p[j]=p[j+1];p[j+1]=temp;}}}Queuethingtem=newLinkedListthing();for(inti=0;ip.length;i++){for(intj=0;jqueue.size();j++){thinga=queue.poll();if(a.score==p[i]){tem.add(a);}else{queue.add(a);}}}queue=tem;for(inti=0;inum;i++){thinga=queue.poll();max[i]=a.id;queue.add(a);}returnmax;}voidshow(){//遍历功能输出每一个数据for(inti=0;iqueue.size();i++){thinga=queue.poll();System.out.println(a.id+””+a.score);queue.add(a);}}}

用来计算从一个点到其他所有点的最短路径的算法,是一种单源最短路径算法。也就是说,只能计算起点只有一个的情况。

使用条件范围

Dijkstra的时间复杂度是O (N2),它不能处理存在负边权的情况。

通常可以在任何图中使用,包括有向图、带负权边的图。

算法描述:

Floyd-Warshall
算法用来找出每对点之间的最短距离。它需要用邻接矩阵来储存边,这个算法通过考虑最佳子路径来得到最佳路径。

      
设起点为s,dis[v]表示从s到v的最短路径,pre[v]为v的前驱节点,用来输出路径。

算法思想

       a)初始化:dis[v]=∞(v≠s); dis[s]=0; pre[s]=0;

Algorithm代码

       b)For (i = 1; i <= n ; i++)

//dist(i,j)为从节点i到节点j的最短距离

            1.在没有被访问过的点中找一个顶点u使得dis[u]是最小的。

Fori←1tondo

            2.u标记为已确定最短路径

Forj←1tondo

            3.For 与u相连的每个未确定最短路径的顶点v

dist(i,j)=weight(i,j)

              if  (dis[u]+w[u][v]<dis[v])

Fork←1tondo//k为“媒介节点”

               {

Fori←1tondo

                  dis[v]=dis[u]+w[u][v];

Forj←1tondo

                  pre[v]=u;

if(dist(i,k)+dist(k,j)dist(i,j))then//是否是更短的路径?

               }

dist(i,j)=dist(i,k)+dist(k,j)

       
c)算法结束:dis[v]为s到v的最短距离;pre[v]为v的前驱节点,用来输出路径。

实现

算法实现步骤:

Java代码

   
设图G用邻接矩阵的方式存储在GA中,GA[I,j]=maxint表示vi,vj是不关联的,否则为权值(大于0的实数)。设集合s用来保存已求得的最短路径的终点序号,初始时s=[vi]表示只有源点,以后每求出一个终点vj就把它加入到集合中并作为新考虑的中间结点。

publicclassFloyd{

   
设数组dist[1..n]用来存储当前求得的最短路径,初始时vi,vj如果是关联的,则dist[j]=权值,否则=maxint,以后,随着考虑的中间结点越来越多,dist[j]可能越来越小。再设一个与dist数组相对应的数组path[1..n],用path[j]来存放当前vi-vj的最短路径上vj点的前驱,初始时为vi的边,如果不存在边,则为0。

privateint[][]dist;

   
执行时,先从s以外的顶点(即待求出最短路径的终点)所对应的dist数组元素中,找出其值最小的元素(假设为dist[m]),该元素的值就是从源点vi到终点vm的最短路径长度,从对应的path[m]中的顶点开始递归直到源点的序列即为最短路径。接着把vm并入集合s中,然后以vm作为新考虑的中间结点,对s以外的每个顶点vj,比较dist[m]+GA[m,j]和dist[j]的大小,若前者小,表明加入中间结点后可以得到更好的方案,即可求得更短的路径,那么就用dist[m]+GA[m,j]替代原来的dist[j],同时把vm存入到path[j]中。重复以上n-2次,即可在dist数组得到从源点到其余各终点的最短路径长度,对应的path数组中保存着相应的最短路径的终点前驱。

privateint[][]path;

算法执行过程图示分析:

publicvoidfloyd(int[][]value){

   图片 1

intlen=value.length;

dist=newint[len][len];

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int map[1000][1000];
 6 int vis[1000];
 7 int dis[1000];
 8 int path[1000];
 9 int n,m,w;
10 int e;
11 const int maxn=999999;
12 void df(int);
13 void print(int, int);
14 int main()
15 {
16     cin>>n>>m;
17     memset(dis,maxn,sizeof(dis));
18     memset(map,maxn,sizeof(map));
19     for(int i=1;i<=m;i++)
20      {
21          int x,y;
22          cin>>x>>y>>w;
23          map[x][y]=map[y][x]=w;
24      }
25     memset(vis,0,sizeof(vis));
26     int a;
27     cin>>a>>e;
28     df(a);
29     print(a,e);
30 } 
31 void df(int s)
32 {
33     for(int i=1;i<=n;i++)
34      {
35          dis[i]=map[s][i];
36          if(dis[i]!=maxn)
37           {
38               path[i]=s;
39           }
40         else path[i]=0;
41      }
42      vis[s]=1;
43      dis[s]=0;
44      int k,min1;
45      for(int i=1;i<=n-1;i++)
46       {
47           k=s;
48           min1=maxn;
49           for(int j=1;j<=n;j++)
50            {
51                if(dis[i]<min1&&vis[j]==0)
52                 {
53                     min1=dis[i];
54                     k=j;
55                 }
56            }
57            vis[k]=1;
58            for(int q=1;q<=n;q++)
59             {
60                 if(vis[q]==0&&dis[q]>dis[k]+map[k][q])
61                  {
62                      dis[q]=dis[k]+map[k][q];
63                      path[q]=k;
64                  }
65             }
66       }
67       cout<<dis[e]<<" ";
68 }
69 void print(int u,int r)
70 {
71     int que[1000];
72     int tot=1;
73     int temp;
74     que[tot]=r;
75     tot++;
76     temp=path[r];
77     while(temp!=u)
78      {
79          que[tot]=temp;
80          tot++;
81          temp=path[temp];
82      }
83      que[tot]=u;
84      for(int i=tot;i>=1;i--)
85       {
86           cout<<que[i]<<"-->"; 
87       }
88 }

path=newint[len][len];

 

for(inti=0;ilen;i++){

             
             
             

for(intj=0;jlen;j++){

path[i][j]=-1;

dist[i][j]=value[i][j];

}

}

for(intk=0;klen;k++){

for(inti=0;ilen;i++){

for(intj=0;jlen;j++){

if(dist[i][k]!=Integer.MAX_VALUE

dist[k][j]!=Integer.MAX_VALUE

dist[i][k]+dist[k][j]dist[i][j]){

dist[i][j]=dist[i][k]+dist[k][j];

path[i][j]=k;

}

}

}

}

}

publicvoidpath(inti,intj){

intk=path[i][j];

if(k==-1)

return;

path(i,k);

System.out.print(-+k);

path(k,j);

}

publicvoiddisPatch(inti,intj){

System.out.println(mindistis:+dist[i][j]);

System.out.print(i);

path(i,j);

System.out.print(-+j);

}

}

dist[][]数组初始化为各顶点间的原本距离,最后存储各顶点间的最短距离。

path[][]数组保存最短路径,与当前迭代的次数有关。初始化都为-1,表示没有中间顶点。在求dist[i][j]过程中,path[i][j]存放从顶点vi到顶点vj的中间顶点编号不大于k的最短路径上前一个结点的编号。在算法结束时,由二维数组path的值回溯,可以得到从顶点vi到顶点vj的最短路径。

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图