问题:
形如输入字符串“<1,2>,<1,3>,<2,2>,<2,4>,<3,2>”的有限集的关系来求自反、对称和传递闭包。
其中上述关系的有限集为A={1,2,3,4}。
思路:
- 自反闭包,在原关系上添加上<x,x>关系即可(x属于任意A中元素)
- 对称闭包,原关系中每有一个<x,y>关系,就添加<y,x>关系即可
- 传递闭包,利用弗洛伊德—沃舍尔算法(一种动态规划,也可用于求多源最短路)求传递闭包
具体代码实现:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1005;
int g[N][N];
int Size;//矩阵大小
void zifan()
{
int a[Size+1][Size+1];//临时存自反矩阵
for(int i=1;i<=Size;i++)//初始化
for(int j=1;j<=Size;j++)a[i][j]=0;
for(int i=1;i<=Size;i++)
{
for(int j=1;j<=Size;j++)
{
if(i==j)a[i][j]=1;//在原矩阵的基础上,正对角线(i==j)上的i->j全令为有关系,赋值为1
else a[i][j]=g[i][j];
}
}
cout<<"自反闭包"<<endl;
for(int i=1;i<=Size;i++)//输出自反矩阵
{
for(int j=1;j<=Size;j++)cout<<a[i][j]<<' ';
cout<<endl;
}
for(int i=1;i<=Size;i++)//输出自反闭包
{
for(int j=1;j<=Size;j++)
if(a[i][j]==1)cout<<'<'<<i<<','<<j<<'>'<<' ';
}
cout<<endl;
}
void duichen()
{
int a[Size+1][Size+1];//存临时对称矩阵
for(int i=1;i<=Size;i++)//初始化
for(int j=1;j<=Size;j++)a[i][j]=0;
for(int i=1;i<=Size;i++)
{
for(int j=1;j<=Size;j++)
{
if(g[i][j]==1)//原矩阵上i->j有关系,则对称矩阵中i->j,j->i均有关系,赋值为1
a[i][j]=a[j][i]=1;
}
}
cout<<"对称闭包"<<endl;
for(int i=1;i<=Size;i++)//输出对称矩阵
{
for(int j=1;j<=Size;j++)cout<<a[i][j]<<' ';
cout<<endl;
}
for(int i=1;i<=Size;i++)//输出对称闭包
{
for(int j=1;j<=Size;j++)
if(a[i][j]==1)cout<<'<'<<i<<','<<j<<'>'<<' ';
}
cout<<endl;
}
void Floyd_Warshall()//弗洛伊德_沃舍尔算法求传递闭包
{
int a[Size+1][Size+1];//存临时传递矩阵
for(int i=1;i<=Size;i++)//初始化
for(int j=1;j<=Size;j++)a[i][j]=g[i][j];
for(int k=1;k<=Size;k++)//枚举每一个中转点
for(int i=1;i<=Size;i++)//枚举每一个起点
for(int j=1;j<=Size;j++)//枚举每一个终点
a[i][j]=a[i][j]|a[i][k]&a[k][j];//i->j的真值 逻辑加 (i->k的真值 逻辑乘 k->j的真值)
cout<<"传递闭包"<<endl;
for(int i=1;i<=Size;i++)//输出传递矩阵
{
for(int j=1;j<=Size;j++)cout<<a[i][j]<<' ';
cout<<endl;
}
for(int i=1;i<=Size;i++)//输出传递闭包
{
for(int j=1;j<=Size;j++)
if(a[i][j]==1)cout<<'<'<<i<<','<<j<<'>'<<' ';
}
cout<<endl;
}
int main()
{
string s;
cin>>s;
for(int i=0;i<s.size();i++)//遍历输入的字符串
{
if(s[i]=='<')//每一个'<'说明有一个关系
{
int x=s[i+1]-'0',y=s[i+3]-'0';//例如<'x','y'>,'x'表示'<'后面一个字符,'y'表示'<'后面第三个字符,然后减去'0'转化为整型
Size=max(Size,max(x,y));//最大的元素便是矩阵的大小
g[x][y]=1;//x->y有关系则赋值为1,无关系全局变量默认为0
}
}
cout<<"原关系矩阵"<<endl;
for(int i=1;i<=Size;i++)//输出原矩阵
{
for(int j=1;j<=Size;j++)cout<<g[i][j]<<' ';
cout<<endl;
}
cout<<endl;
zifan();//求自反闭包
cout<<endl;
duichen();//求对称闭包
cout<<endl;
Floyd_Warshall();//求传递闭包
return 0;
}