Floyd算法功能总结+详细讲解~~

佛洛伊德算法用于求多源点的最短路径算法~~当然这是最原始的功能。 

佛洛伊德算法时间复杂度 为O(n^3)次方。

求最短路,讲的是 如果两点之间的边的距离大于   这两点经过其他点所到达的距离,那么就把最短距离替换成那条经过第三个点所到达的边的距离。(a->b的距离大于a->k->b的距离)a到b的距离大于a经过k再到b(当然这里所说的第三个点不一定就真的是三个点,可能有很多很多个点,见下两张图所示)。请读者仔细阅读,肯定能理解佛洛伊德的流程。





佛洛伊德代码:

void floyd()
{
    for(int k=1;k<=n;k++)
    {
        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];//当i,j的原来的边的最短距离,大于经过k点所到达的距离那么就替换。
                   
                }
            }
        }
    }
}

到这里相信大家对佛洛伊德求最短路也有了一个理解了~~~

大家可以练练手了 做道题吧:~~

hdu六度分离。 做下这个题目吧:

/*
思路:
求任意两点之间的最短路,最后只需判断最远两点距离是否大于7即可。
*/
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 999999
using namespace std;
int map[101][101];
int n,m;
int main()
{
    int x,y;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int i,j,k;
        memset(map,MAX,sizeof(map));
        while(m--)
        {
            scanf("%d%d",&x,&y);
            map[x][y]=map[y][x]=1;

        }


        for(k=0; k<n; k++)//求最短路
            for(i=0; i<n; i++)
                for( j=0; j<n; j++)
                {
                    if(map[i][k]+map[k][j]<map[i][j])
                        map[i][j]=map[i][k]+map[k][j];
                }


    int f=1;
        for(i=0; i<n; i++)
        {
            for(j=0; j<n; j++)//判断任意两点的距离有没有大于7
            {
                if(map[i][j]>7)
                {
                    printf("No\n");
                    f=0;
                    break;
                }
             }
             if(!f)
                break;
        }

        if(f)
            printf("Yes\n");
    }

        return 0;
    }

以上就是第一个基础功能求最短路的

功能2 :求无向图中可以删除一些边,使得任意两点的最短路不改变,求这些边能删除的最大的条数。

这个题

思路是这样:

 首先先在输入边的时候将重边去掉,保留最小的。然后根据佛洛依德算法的性质。
如果原来两点的最短距离大于经过第三个点的最短距离的话,那么我们就将这两点的最短距离
替换成经过第三条边的最短距离,因为那个短,既 将这条边替换成经过第三个点的边。
那么原来的边我们就可以删除。
但是~~~当两点之间本来没有边的情况下,我们肯定是经过第三个点所到达的。那么就没有替换
原来的边,这种情况的话,就直接continue

大家可以做下FZU2271
代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
int dis[101][101];
int dis1[101][101];
bool vis[101][101];
int n,m;
void floyd()
{
    for(int k=1;k<=n;k++)
    {
        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];//当i,j的原来的边的最短距离,大于经过k点所到达的距离那么就替换。
                    vis[i][j]=1;//当这条边被替换掉,则做好标记
                }
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int cas=1;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                dis[i][j]=INF;
            }
        }
        for(int i=1;i<=m;i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            if(dis[x][y]!=INF)//将重边去掉
            {
                sum++;
            }
            if(dis[x][y]>w) dis[x][y]=w,dis[y][x]=w;//选权值最小的边
        }
        memcpy(dis1,dis,sizeof(dis1));
        memset(vis,0,sizeof(vis));
        floyd();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                if(dis1[i][j]==INF) continue;//当原来的两点没有边,就直接continue,因为这两点肯定是经过其他点到的所以没有替换
                if(dis[i][j]<=dis1[i][j]&&vis[i][j]) sum++;//当i,j的边小于等于
            }
        }
        printf("Case %d: %d\n",cas++,sum);
    }
}

功能三:佛洛伊德求无向图的最小环。

题目:URAL - 1004



代码:

#include <stdio.h>
#include <string.h>
#define inf 0x3f3f3f3f
#define maxn 102
int map[maxn][maxn], pre[maxn][maxn];
int dist[maxn][maxn], store[maxn], minCircle;
void getMap(int n, int m)
{
    int i, u, v, d;
    memset(map, 0x3f, sizeof(map));
    for(i = 0; i < m; ++i){
        scanf("%d%d%d", &u, &v, &d);
        if(d < map[u][v])
            map[u][v] = map[v][u] = d;
    }
    memcpy(dist, map, sizeof(map));
}
void solve(int n)
{
    int k, i, j, id, tmp; minCircle = inf;
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= n; ++j) pre[i][j] = j;//最短路的路径初始化为~~j,表示i到j直接经过j。
    for(k = 1; k <= n; ++k){
        for(i = 1; i <= k-1; ++i){
            for(j = i+1; j <= k-1; ++j)
                if( dist[i][j] != inf && map[i][k] != inf &&map[k][j]!=inf&& dist[i][j] + map[i][k] +map[k][j] < minCircle){
                    minCircle = dist[i][j] + map[i][k] + map[k][j];//此处就是上图的环了。
                    tmp = i; id = 0;
                    while(tmp != j){//记录环的路径
                        store[id++] = tmp;
                        tmp = pre[tmp][j];
                    }
                    store[id++] = j; store[id++] = k;
                }
        }
        for(i = 1; i <= n; ++i)//这里还是求任意两点的最短距离。
            for(j = 1; j <= n; ++j)
                if(dist[i][k] != inf && dist[k][j] != inf &&
                    dist[i][k] + dist[k][j] < dist[i][j]){
                    dist[i][j] = dist[i][k] + dist[k][j];
                    pre[i][j] = pre[i][k];//记录最短的路径
                }
    }
    if(minCircle == inf){
        printf("No solution.\n"); return;
    }
    for(i = 0; i < id; ++i)
        if(i != id - 1) printf("%d ", store[i]);
        else printf("%d\n", store[i]);
}
int main()
{
    int n, m;
    while(scanf("%d", &n)&&n!=-1){
         scanf("%d",&m);
        getMap(n, m);
        solve(n);
    }
}

还有其他功能 持续跟新~~~~~~~~~~~~~

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值