有向图的传递闭包实现三种实现(Warshall+DFS+BFS)

22 篇文章 0 订阅
13 篇文章 1 订阅

一、传递闭包:

定义:

n个顶点的有向图的传递闭包可以定义为一个n阶布尔矩阵T[n][n],如果i能到jT[i][j] =1,否则T[i][j] =0

意义:

对于无向图,我们可以通过并查集来实现两个顶点是否有通路的快速查询。但有向图不能有并查集,所以现在可以用传递闭包了(当然无向图也可以用)

通过Floyd-Warshall算法https://blog.csdn.net/qq_40691051/article/details/103278207
得到的dist数组其实就可以充当传递闭包了,而第一种实现跟上面这个算法差不多,叫Wharshall算法(上面的他也独立发明了)

在这里插入图片描述
在这里插入图片描述

代码1:

reach[][]就是那个布尔矩阵(传递闭包)

#include<iostream>
#include<vector>

using namespace std;

#define V 4

void printSolution(bool reach[][V])
{
	for(int i = 0; i < V; i++)
	{
		for(int j = 0; j < V; j++)
		{
			cout<<reach[i][j];
		}
		cout<<endl;
	}
	cout<<endl;
}  

void transitiveClosure(bool  graph[][V])
{
	bool reach[V][V];
	
	for(int i = 0; i < V; i++)
	{
		for(int j = 0; j < V; j++)
		{
			reach[i][j] =  graph[i][j];	
		}
	}
	
	for(int k = 0; k < V; k++)
	{
		for(int i = 0; i < V; i++)
		{
			for(int j = 0; j < V; j++)
			{
				reach[i][j] = reach[i][j] ||( reach[i][k] && reach[k][j]);
			}
		}
	}
	
	printSolution(reach); 
}
int main() 
{ 

       /* 
       (0)------->(3) 
        |         /|\ 
        |          | 
        |          |  
       \|/         | 
       (1)------->(2) 
                      
	  */
    bool graph[V][V] = { {1, 1, 0, 1}, 
                        {0, 1, 1, 0}, 
                        {0, 0, 1, 1}, 
                        {0, 0, 0, 1} 
                      }; 
  
    // Print the solution 
    transitiveClosure(graph); 
    return 0; 
} 

在这里插入图片描述

实现2、3:

一开始先把reach[][]初始化为false,然候通过DFSBFS去从遍历(只遍历能到的点),能到就标记为true

#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<memory.h>
using namespace std;

class Graph
{
	int n;				//顶点数 
	list<int>*adj;		//邻接表 
	bool **reach;	    //二维数组记录,reach[i][j] == 1(ture) ===> i->j有路 
	void BFSUtil(int src);
	void DFSUtil(int src, int v);
public:
	Graph(int _n);
	~Graph(){ delete [] adj; delete [] reach;}
	void addEdge(int u, int v){ adj[u].push_back(v); }
	void transitiveClosure();
}; 
Graph::Graph(int _n)
{
	n = _n;
	adj = new list<int>[_n];
	reach = new bool*[_n];
	for(int i = 0; i < _n; i++)
	{
		reach[i] = new bool[_n];
		memset(reach[i], false, _n*sizeof(bool));	//一开始初始化为false
	}
} 
void Graph::BFSUtil(int src)
{
	queue<int>q;
	q.push(src);
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		reach[src][u] = true;
		
		list<int>::iterator it;
		for(it = adj[u].begin(); it != adj[u].end(); it++)
		{
			int v = *it;
			if(reach[src][v] == false)
			{
				q.push(v);
			} 
		}
	}
} 
void Graph::DFSUtil(int src, int v) 
{
	reach[src][v] = true;
	
	list<int>::iterator it;
	for(it = adj[v].begin(); it != adj[v].end(); it++)
	{
		if(reach[src][*it] == false)
		{
			DFSUtil(src , *it);
		} 
	}
}
void Graph::transitiveClosure()
{
	for(int i = 0; i < n; i++)
	{
		//DFSUtil(i , i);		//每个点都能从自己到自己 
		BFSUtil(i); 
	}
	//打印
	for (int i = 0; i < n; i++) 
    { 
        for (int j = 0; j < n; j++) 
            cout << reach[i][j] << " "; 
        cout << endl; 
    } 
}
int main() 
{ 
    Graph g(4); 
    g.addEdge(0, 1); 
    g.addEdge(0, 2); 
    g.addEdge(1, 2); 
    g.addEdge(2, 0); 
    g.addEdge(2, 3); 
    g.addEdge(3, 3); 
  
    cout << "Transitive closure matrix is \n"; 
    g.transitiveClosure(); 
  
    return 0; 
} 

在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值