Floyd-Warshall方法求有向图的传递闭包 收藏


有向图G的传递闭包定义为:G*=(V,E*),其中
E*={(i,j)}:图G中存在一条从i到j的路径。

在floyd-warshall求每对顶点间的最短路径算法中,可以通过O(v^3)的方法求出图的传递闭包。可以位每条边赋以权值1,然后运行Floyd-Wareshall。如果从i    到j存在一条路径,则d(i,j)<N,否则d(i,j)=MAX。
 一种改进的算法是:由于我们需要的只是判断是否从i到j存在一条通路,所以在Floyd-Wareshall中的动态规划比较中,我们可以把min和+操作改为逻辑or(||    )和逻辑与(&&)。
 设tk(i,j)=1表示从i到j存在一条通路p,且p的所有中间节点都在0,1,2,...,k中,否则tk(i,j)=0。我们把边(i,j)加入到E*中当且仅当tn(i,j)=1。view plaincopy to clipboardprint?
#include <iostream>  
using namespace std;  
const int N = 4;  
const int E = 5;  
const int MAX = 0xffff;  
int ** g;  
int ** transitive_closure(int **g)  
{  
    int i = 0;  
    int j = 0;  
    int **t = new int*[N];//tk(i,j)=1表示从顶点i到顶点j存在一条路经,且路径中间节点在0,1,2,...,k中  
    /* 
     * t-1(i,j) = 0如果i!=j且g[i][j] == MAX,否则t0(i,j) =1. 
     * 
     * tk(i,j) = tk-1(i,j) || (tk-1(i,k)&&tk-1(j,k))当0<=k<N 
     */ 
    for(i=0;i<N;i++)  
            t[i] = new int[N];  
    for(i=0;i<N;i++)//当k==-1时,即从i到j没有中间节点时,初始化t-1(i,j)  
            for(j=0;j<N;j++)  
                    if(i==j || g[i][j] < MAX)  
                            t[i][j] = 1;  
                    else 
                            t[i][j] = 0;  
    int **t1,**t2;//t1表示迭代中的tk-1,t2表示迭代中的tk  
    t1 = t;  
    int k = 0;  
    for(k=0;k<N;k++)  
    {  
            t2 = new int *[N];  
            for(i=0;i<N;i++)  
            {  
                    t2[i] = new int[N];  
                    for(j=0;j<N;j++)  
                    {  
                        t2[i][j] = t1[i][j] || (t1[i][k] && t1[k][j]);  
                    }  
            }  
            for(i=0;i<N;i++)  
                    delete []t1[i];  
            delete []t1;  
            t1 = t2;  
    }  
    return t1;  
}  
int main()  
{  
    int i = 0;  
    int j = 0;  
    g = new int *[N];  
    for(i=0;i<N;i++)  
    {  
            g[i]= new int[N];  
    }  
    for(i=0;i<N;i++)  
            for(j=0;j<N;j++)  
                    if(i==j)  
                            g[i][j] = 0;  
                    else   
                            g[i][j] = MAX;  
    int c = 0;  
    while(c<E)  
    {  
        cin >> i;  
        cin >> j;  
        cin >> g[i][j];  
        c++;  
    }  
    int ** t = transitive_closure(g);  
    for(i=0;i<N;i++)  
    {  
            for(j=0;j<N;j++)  
                    cout << t[i][j] << " ";  
            cout << endl;  
    }  

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/09/13/4548314.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值