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

你可能感兴趣的:(floyd)