码迷,mamicode.com
首页 > 其他好文 > 详细

多源最短路径Floyd、Floyd求最小环【模板】

时间:2015-05-04 22:07:36      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:

Floyd算法:用来找出每对点之间的最短距离。图可以是无向图,也可以是有向图,边权可为正,也可以为负,唯一要求是不能有负环。
1.初始化:将Map[][]中的数据复制到Dist[][]中作为每对顶点之间的最短路径的初值,Pre[i][j] = i 表示 i 到 j 路径中 j 的前一节点。
2. k 从 1 到 N 循环 N 次,每次循环中,枚举图中不同的两点 i,j,如果Dist[i][j] > Dist[i][k] + Dist[k][j],则更新Dist[i][j] = Dist[i][k] + Dist[k][j],更新Pre[i][j] = Pre[k][j]。
只要图中不存在负环就可以得出正确的答案,关于Floyd算法对负环的判定,参考下边Floyd求最小环。

const int MAXN = 110;
const int INF = 0xffffff0;

int Map[MAXN][MAXN], Dist[MAXN][MAXN],Pre[MAXN][MAXN];
//Pre[i][j] = i表示i到j路径中j的前一节点
void Floyd(int N)
{   //初始化
    for(int i = 1; i <= N; ++i)
    {
        for(int j = 1; j <= N; ++j)
        {
            Dist[i][j] = Map[i][j];
            Pre[i][j] = i;
        }

    }
    for(int k = 1; k <= N; ++k)
    {
        for(int i = 1; i <= N; ++i)
        {
            for(int j = 1; j <= N; ++j)
            {   //如果Dist[i][j] > Dist[i][k] + Dist[k][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[k][j];  //更新Pre[i][j]
                }    
            }
        }
    }
}

如果求点u到点v能达到的最长边尽可能短的路径上最长边为多少,将循环内部改为如下代码:

int tMax;   //这里边求的是能达到的路径上最长边最小为多少  
                if(Dist[i][k] > Dist[k][j])  
                    tMax = Dist[i][k];  
                else  
                    tMax = Dist[k][j];  
                if(Dist[i][j] > tMax)  
                    Dist[i][j] = tMax;  

Floyd求最小环
不能在Map[][]数组上直接计算,因为判断过程中用到了Map[][]原始值。

const int MAXN = 110;
const int INF = 0xffffff0;
int temp,Map[MAXN][MAXN],Dist[MAXN][MAXN],pre[MAXN][MAXN],ans[MAXN*3];

void Solve(int i,int j,int k)
{
    temp = 0;   //回溯,存储最小环
    while(i != j)
    {
        ans[temp++] = j;
        j = pre[i][j];
    }
    ans[temp++] = i;
    ans[temp++] = k;
}
void Floyd(int N)
{
    for(int i = 1; i <= N; ++i)
        for(int j = 1; j <= N; ++j)
        {
            Dist[i][j] = Map[i][j];
            pre[i][j] = i;
        }
    int MinCircle = INF;    //最小环
    for(int k = 1; k <= N; ++k)
    {
        for(int i = 1; i <= N; ++i)
        {
            for(int j = 1; j <= N; ++j)
            {
                if(i != j && Dist[i][j] != INF && Map[i][k] != INF && Map[k][j] != INF
                   && Dist[i][j] + Map[i][k] + Map[k][j] < MinCircle)
                {
                    MinCircle = min(MinCircle, Dist[i][j] + Map[i][k] + Map[k][j]);
                    Solve(i,j,k);   //回溯存储最小环
                }
            }
        }

        for(int i = 1; i <= N; ++i)
        {
            for(int 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[k][j];  //记录点i到点j的路径上,j前边的点
                }
            }
        }
    }

    if(MinCircle == INF)    //不存在环
    {
        printf("No solution.\n");
        return;
    }
    //如果求出最小环为负的,原图必定存在负环
    for(int i = 0;i < temp; ++i)    //输出最小环
        if(i != temp-1)
            printf("%d ",ans[i]);
        else
            printf("%d\n",ans[i]);
}

多源最短路径Floyd、Floyd求最小环【模板】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/45486825

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!