Floyd最小环求最短路
来源:互联网 发布:2000w酒店数据 在线 编辑:程序博客网 时间:2024/06/11 05:54
1 定义:
通常来说最小环是针对有向图而言
从一个点出发,经过一条简单路径回到起点成为环.图的最小环就是所有环中长度最小的.
2.怎样求最小环呢?
1传统的解决方法(dijkstra):
任意一个环的权值,我们都可以看成两个有边相连的结点i、j的直接距离加上i、j间不包含边(边i->j)的最短路径。求最短路径我们第一个想到的就是Dijkstra算法。而Dijkstra所求的是一个点到所有点的最短距离。用Dijkstra所求的i、j的最短距离一定是i、j的直接距离(如果i,j连通),所以我们需要先将i、j的边从图中删除(若i,j不连通,则不用删除),再用Dijkstra求新图中i、j的最短距离即可。所以我们每次在图中选取一条边,把它从图中删掉.然后对删掉的那条边所对应的2点进行Dijkstra,也就是m次Dijkstra。
2.floyd求最小环:
抛开Dijkstra算法,进而我们想到用Floyd算法。我们知道,Floyd算法在进行时会不断更新矩阵dist(k)。设dist[k,i,j]表示从结点i到结点j且满足所有中间结点,它们均属于集合{1,2,⋯ ,k}的一条最短路径的权。其中dist[0,i,j ]即为初始状态i到j的直接距离。对于一个给定的赋权有向图, 求出其中权值和最小的一个环。我们可以将任意一个环化成如下形式:u->k->v ->(x1-> x2-> ⋯ xm1)-> u(u与k、k与v都是直接相连的),其中v ->(x1-> 2-> ⋯ m)-> u是指v到u不经过k的一种路径。
在u,k,v确定的情况下,要使环权值最小, 则要求 (x1一>x2->⋯一>xm)->u路径权值最小.即要求其为v到u不经过k的最短路径,则这个经过u,k,v的环的最短路径就是:[v到u不包含k的最短距离]+dist[O,u,k]+dist[O,k,v]。我们用Floyd只能求出任意2点间满足中间结点均属于集合{1,2,⋯ ,k}的最短路径,可是我们如何求出v到u不包含k的最短距离呢?
现在我们给k加一个限制条件:k为当前环中的序号最大的节点(简称最大点)。因为k是最大点,所以当前环中没有任何一个点≥k,即所有点都<k。因为v->(x1->x2->......xm)->u属于当前环,所以x1,x2,⋯ ,xm<k,即x1,x2.⋯。xm≤k一1。这样,v到u的最短距离就可以表示成dist[k一1 ,u,v]。dist[k一1,v,u]表示的是从v到u且满足所有中间结点均属于集合{1,2,⋯ ,k一1}的一条最短路径的权。接下来,我们就可以求出v到u不包含k的最短距离了。这里只是要求不包含k,而上述方法用的是dist[k一1,v,u],求出的路径永远不会包含k+l,k+2,⋯ 。万一所求的最小环中包含k+1,k+2,⋯ 怎么办呢?的确,如果最小环中包含比k大的节点,在当前u,k,v所求出的环显然不是那个最小环。然而我们知道,这个最小环中必定有一个最大点kO,也就是说,虽然当前k没有求出我们所需要的最小环,但是当我们从k做到kO的时候,这个环上的所有点都小于kO了.也就是说在k=kO时一定能求出这个最小环。我们用一个实例来说明:假设最小环为1—3—4—5—6—2—1。的确,在u=l,v=4,k=3时,k<6,dist[3,4,1]的确求出的不是4—5—6—2—1这个环,但是,当u=4,v=6,k=5或u=5,v=2,k=6时,dist[k,v,u]表示的都是这条最短路径.所以我们在Floyd以后,只要枚举u.v,k三个变量即可求出最小环。时间复杂度为O(n3)。我们可以发现,Floyd和最后枚举u,v,k三个变量求最小环的过程都是u,v,k三个变量,所以我们可以将其合并。这样,我们在k变量变化的同时,也就是进行Floyd算法的同时,寻找最大点为k的最小环。
Floyd求两点间最短路
//Floyd-Warshall算法核心语句 for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][k]<inf && e[k][j]<inf && e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
http://acm.fzu.edu.cn/problem.php?pid=2090
#include<stdio.h>#include<string.h>#define M 107#define inf 0x3f3f3fusing namespace std;int g[M][M],dis[M][M],path[M][M],pre[M];int n,m,num,mincircle,count;void init(){ for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { g[i][j]=dis[i][j]=inf; } g[i][i]=dis[i][i]=0; }}void dfs(int i,int j){ int k=path[i][j]; if(k==0) { pre[num++]=j; return ; } dfs(i,k); dfs(k,j);}void Floyd(){ mincircle=inf; for(int k=1; k<=n; k++) { for(int i=1; i<k; i++)//求环 for(int j=i+1; j<k; j++) { if(mincircle>dis[i][j]+g[i][k]+g[k][j]) { mincircle=dis[i][j]+g[i][k]+g[k][j]; num=0; pre[num++]=i; dfs(i,j); pre[num++]=k; count=1; } else if(mincircle==dis[i][j]+g[i][k]+g[k][j])//记录次数 count++; } for(int i=1; i<=n; i++)//求最短路 for(int j=1; j<=n; j++) if(dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j]=dis[i][k]+dis[k][j]; path[i][j]=k; } }}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); int a,b,c; for(int i=1; i<=m; i++) { scanf("%d%d%d",&a,&b,&c); if(g[a][b]>c) { g[a][b]=g[b][a]=c; dis[a][b]=dis[b][a]=c; } } memset(path,0,sizeof(path)); Floyd(); if(mincircle==inf) printf("-1\n"); else printf("%d %d\n",mincircle,count); } return 0;}
http://poj.org/problem?id=1734
题意:求一个图中最小环,输出路径。
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int N=105;const int INF=9999999;int map[N][N],dist[N][N];int road[N][N],path[N];int m,n,cnt,ans;void Init(){ for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { dist[i][j]=INF; road[i][j]=0; } }}/**记录最小环的路径*/void Record(int s,int t){ if(road[s][t]) { Record(s,road[s][t]); Record(road[s][t],t); } else path[cnt++]=t;}void Floyd(){ int i,j,k; ans=INF; for(k=1;k<=n;k++) { /**最小负环的判定*/ for(i=1;i<k;i++) { for(j=i+1;j<k;j++) { if(ans>dist[i][j]+map[i][k]+map[k][j]) { ans=dist[i][j]+map[i][k]+map[k][j]; cnt=0; path[cnt++]=i; Record(i,j); path[cnt++]=k; } } } /**正常floyd部分*/ for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(dist[i][j]>dist[i][k]+dist[k][j]) { dist[i][j]=dist[i][k]+dist[k][j]; road[i][j]=k; } } } }}int main(){ int i,j,u,v,w; while(cin>>n>>m) { Init(); while(m--) { cin>>u>>v>>w; if(w<dist[u][v]) /**如果有重边,就取最小的权值*/ { dist[u][v]=w; dist[v][u]=w; } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=dist[i][j]; Floyd(); if(ans==INF) puts("No solution."); else { cout<<path[0]; for(int i=1;i<cnt;i++) cout<<" "<<path[i]; cout<<endl; } } return 0;}
- Floyd最小环求最短路
- floyd求最小环
- floyd求最小环
- floyd求最小环
- floyd求最小环
- FLOYD 求最小环
- floyd求最小环
- floyd求最小环
- Floyd求最小环
- floyd求最小环
- floyd求最小环
- floyd算法求最小环
- Floyd算法求最小环
- floyd求最小环 模板
- hdu1599 floyd 求最小环
- 求最小环(floyd,dijkstra)
- 最短路(3)--floyd和用floyd求最小环
- 多源最短路·floyd && 最小环算法
- 第七次 HTML作业
- 2016.4.13Python中的filter
- 03-树2 List Leaves (25分)
- Android Studio获取SHA1值
- 【Android】工具 —— Eclipse常用功能
- Floyd最小环求最短路
- HTML简介
- [leetcode]328. Odd Even Linked List
- java编程思想第四版-嵌套类
- stream 流是什么?
- get请求和post请求提交的区别?
- 用wampserver中的phpMyAdmin时会提示 Access denied(访问被拒绝)
- Python装饰器
- 浅谈如何在MySQL中进行模糊搜索的一些问题