zoukankan      html  css  js  c++  java
  • 算法导论 第二十五章:有向图的传递闭包

       已知一有向图G=<V,E>,顶点集合V={1,2,...,n},我们可能希望确定对全部顶点对i,j ∈ V,图G中事发后都存在一条从i到 j 的路径。G的传递闭包定义为图,当中:

                                                           

         在Θ(n^3)时间内计算出图的传递闭包的一种方法是对E中每条边赋以权值1。然后执行Floyd-Warshall算法。假设顶点i到顶点j存在一条路径,则d(i,j)<n。否则d(i,j)=∞。

       还有一种方法与Floyd-Warshall类似,能够在Θ(n^3)内计算出图G的传递闭包,且在实际中能够节省时空需求,详细原理例如以下:

           将Floyd-Warshall中的min和+操作。用对应的逻辑运算∨(逻辑OR)和∧(逻辑AND)来取代,对于i,j,k = 1,2,...,n,假设图G中从顶点i到顶点j存在一条通路,且全部中间顶点均属于集合{1,2,...k},则定义例如以下:

    当k ≥ 1时,有:

        

    伪代码:

    EG:


    完整代码:

    #include<iostream>
    #include<climits>
    #include<iomanip>
    using namespace std;
    
    typedef int vType;
    typedef int wType;
    typedef struct edge{
    	vType u;   // the start of edge
    	vType v;   // the end of edge
    	}edge;
    typedef struct MGraph{
    	int vNum;
    	int eNum;
    	vType *V;
    	edge *E;
    	}MGraph;
    
    void Matrix_Print(bool **M,int n)
    {
    	for(int i=0; i< n; i++)
    	{ 
    		for(int j=0; j<n; j++)
    			cout<<setw(2)<<M[i][j];
    		cout<<endl;
    		}
    	}
    int Locate(MGraph &G,vType v)
    {
    	for(int i=0; i<G.vNum; i++)
    		if(v == G.V[i])
    			return i;
    	return -1;
    	}	
    void Graph_Init(MGraph &G,vType V[],edge E[])
    {
    	//init the vertices 
    	G.V = new vType[G.vNum];
    	for(int i=0; i<G.vNum; i++)
    		G.V[i] = V[i];
    	//init the edge
    	G.E = new edge[G.eNum];
    	for(int i=0 ; i<G.eNum; i++){
    		G.E[i].u = E[i].u;
    		G.E[i].v = E[i].v;
    		} 
    	}
    bool **Matrix_Copy(bool **M,int n)
    {
    	bool **T = new bool*[n];
    	for(int i=0; i<n; i++)
    		T[i] = new bool[n];
    
    	for(int i=0; i<n; i++)
    		for(int j=0; j<n; j++)
    			T[i][j] = M[i][j];
    	return T;
    	}
    /*----------------------Transitive Closure Alogrithm-----------------------------*/
    bool **T;
    bool **Transitive_Closure(MGraph &G){
    	int n = G.vNum;
    	//alloc memory for matrix T;
    	T = new bool*[n];
    	for(int i=0; i<n; i++)
    		T[i]= new bool[n];
    	//when beginning,matrix T denote T[0]
    	for(int i =0 ; i<n; i++)
    		for(int j=0; j<n; j++)
    			if(i == j)
    				T[i][j] = 1;
    			else
    				T[i][j] = 0;
    	for(int i=0; i<G.eNum; i++)
    	{
    		int u_i = Locate(G,G.E[i].u);
    		int v_i = Locate(G,G.E[i].v);
    		T[u_i][v_i] = 1;
    		}
    
    	bool **tempT = new bool*[n];
    	for(int i=0; i<n; i++)
    		tempT[i] = new bool[n];
    	for(int k=0; k<n; k++){
    		tempT = Matrix_Copy(T,n);
    		for(int i=0; i<n; i++)
    			for(int j=0; j<n; j++)
    				T[i][j] = tempT[i][j] | (tempT[i][k] & tempT[k][j]);
    		//cout<<"The "<<k<<"th round is:"<<endl;
    		//Matrix_Print(T,n);
    		}
    	return T;
    	}
    /*-------------------------------------------------------------------------------*/
    int main()
    {
    	vType V[]={1,2,3,4};
    	edge  E[]={{2,3},{2,4},{3,2},{4,1},{4,3}};
    	MGraph G;
    	G.vNum = sizeof(V)/sizeof(vType);
    	G.eNum = sizeof(E)/sizeof(edge) ;
    	Graph_Init(G,V,E);
    	T = Transitive_Closure(G);
    	cout<<"The final transitive closure matrix is:"<<endl;
    	Matrix_Print(T,G.vNum);
    	return 0;
    	}
    

    执行结果:



    【注:若有错误。请指正~~~】

  • 相关阅读:
    面试题:找出数组中只出现一次的2个数(异或的巧妙应用)(出现3次)
    线段树 | 第1讲 (给定区间求和)(转)
    C++中的静态多态和动态多态(转)
    ARP与RARP详细解析(转)
    排序算法之归并排序
    byte数组使用Arrays.asList转换List出错
    排序算法之希尔排序
    排序算法之冒泡排序、选择排序、插入排序
    Tomcat配置优化
    内连接、左外连接、右外连接、全外连接、交叉连接
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6797012.html
Copyright © 2011-2022 走看看