一、传递闭包:
定义:
有n
个顶点的有向图的传递闭包可以定义为一个n
阶布尔矩阵T[n][n]
,如果i
能到j
则T[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
,然候通过DFS
或BFS
去从遍历(只遍历能到的点),能到就标记为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;
}