传递闭包的计算(Warshall)

O(n^3)的高效闭包算法
算法内容:1.做出关系R的矩阵M
2.枚举每一列,以这一列对应的元素为中间元素去创造新的关系(一行一行来做,如果当前行对应的元素与列对应的元素有关系,例如aRb,则考虑<b,…>有无关系,若有关系则aR…,具体实现就是M[a][…] |= M[b]
有点类似于多源最短路算法,也是一种动态规划的思想,假设当前枚举到i列,此时矩阵就是只借助前i个点进行扩展,这时候矩阵的结果已经是站在借助前i-1个节点扩展过的结果了,所以此时扩展得来的关系未必只借助了i点,可能还借助了1-i-1的若干点,而这也就是这个算法的巧妙之处所在。
另外,Wallshall算法在离散数学中还是比较重要的,偏序关系的哈斯图cover关系的求解以及可达矩阵的求解都用到了Wallshall算法。
代码实现:

# include <iostream>
# include <map>

using namespace std;

const int MAX_N = 100;

bool Matrix[MAX_N][MAX_N];
int n;
map<char, int> ma_1;
map<int, char> ma_2;

int main() {
	cout << "输入集合中的元素个数:\n";
	cin >> n;
	cout << "输入集合中各元素:\n";
	for (int i = 0; i < n; i++) {
		char c;
		cin >> c;
		ma_1[c] = i;
		ma_2[i] = c;
	}
	cout << "输入各关系:\n";
	char a, b;
	while (cin >> a >> b)
		Matrix[ma_1[a]][ma_1[b]] = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (Matrix[j][i]) {
				for (int k = 0; k < n; k++) {
					Matrix[j][k] |= Matrix[i][k];
				}
			}
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (Matrix[i][j]) {
				cout << "<" << ma_2[i] << "," << ma_2[j] << ">\n";
			}
		}
	}
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值