最小环 floyd java_Floyd最小环

最小环:从一个点出发,经过一条简单路径回到起点成为环.图的最小环就是所有环中长度最小的.

怎样求最小环呢?

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,即所有点都(x1->x2->......xm)->u属于当前环,所以x1,x2,⋯ ,xm

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include

3 #include

4 #define _Clr(x, y) memset(x, y, sizeof(x))

5 #define INF 0xfffffff

6 #define N 110

7 using namespacestd;8

9 intmat[N][N], dist[N][N];10 int next[N][N]; //next[i][j]表示i到j经历的第一个点。

11 intpath[N];12 intcnt, n;13

14 voidFloyd()15 {16 int mins=INF;17 for(int k=1; k<=n; k++)18 {19 for(int i=1; i

24 {25 mins =tmp;26 cnt=0;27 int p =i;28 while(p!=j) //记录最小环的路径

29 {30 path[cnt++] =p;31 p =next[p][j];32 }33 path[cnt++] =j;34 path[cnt++] =k;35 }36 }37 for(int i=1; i<=n; i++)38 for(int j=1; j<=n; j++)39 {40 if(dist[i][k]+dist[k][j]

50 {51 for(int i=0; i

56 voidInit()57 {58 for(int i=1; i<=n; i++)59 for(int j=1; j<=n; j++)60 {61 mat[i][j] = dist[i][j] =INF;62 next[i][j] =j;63 }64 }65 intmain()66 {67 intm, a, b, c;68 while(~scanf("%d%d", &n, &m))69 {70 Init();71 while(m--)72 {73 scanf("%d%d%d", &a, &b, &c);74 if(c

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值