头像

欢迎来到我的博客

分享题解与总结

传递闭包

传递闭包

屏幕截图 2026-03-15 202107

屏幕截图 2026-03-15 202123

思路:

Warshall算法求传递闭包

  1. 用原始二元关系\(R[i][j]\)\(T[i][j]\)赋初值

  2. 类似Floyd-Warshall算法,三层循环

    用外层k,更新 \(i->j\)

    这里的更新指的是:假如\(T[i][k]=1\)\(T[k][j]=1\),则\(T[i][j]\)应该被赋为1

    形象的说:i,j通过k“粘”了起来(i->k,k->j,去掉连接点k,i->j直接相连)

优点:

避免了使用\(t(R)=R∪R^2∪R^3∪...∪R^n\),即\(M_t=M+M^2+M^3+...+M^n\),时间复杂度较高的方法

int n,a[N][N],b[N][N];

void warshall()//传递闭包 t(R)
{
	for(int k=1;k<=n;++k){
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				if(b[i][k]==1&&b[k][j]==1)
					b[i][j]=1;
			}
		}
	}
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			cin>>a[i][j];
			b[i][j]=a[i][j];
		}
	}
	warshall();
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			cout<<b[i][j]<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

自反闭包和对称闭包:

void getr()//新增:自反闭包 r(R)
{
	for(int i=1;i<=n;++i){//加环
		b[i][i]=1;
	}
}

void gets()//新增:对称闭包 s(R)
{
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){//如果有单向边 加一条反向的边
			if(b[i][j]==1)
				b[j][i]=1;
		}
	}
}
posted @ 2026-03-15 20:36  king_steph1209  阅读(16)  评论(0)    收藏  举报