二元关系的关系的闭包

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二元关系的关系的闭包相关的知识,希望对你有一定的参考价值。

参考技术A

设R是非空集合A上的关系, R的自反(对称或传递)闭包是A上的关系R\' ,满足
(1) R\'是自反的(对称的或传递的)
(2)
(3) 对A上任何包含R的自反(对称或传递)关系R\'\'有
一般将R的自反闭包记作r(R),对称闭包记作s(R) ,传递闭包记作t(R)。
下列给出了构造闭包的方法:



对于有限集合A 上的关系R ,存在一个正整数s,使得 ,且s不超过A的元素数。
求传递闭包是图论中一个非常重要的问题,例如给定了一个城市的交通地图,可利用求传递闭包的方法获知任意两个地点之间是否有路相连通。可以直接利用关系矩阵相乘来求传递闭包,但那样做复杂度比较高;好一点的办法是在计算矩阵相乘的时候用分治法降低时间复杂度;但最好的方法是利用基于动态规划的Floyd-Warshall算法来求传递闭包。

hdu1704传递闭包

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1704

传递闭包定义在关系集R上,如果关系R中既有元组(x,y)又有元组(y,z)则元组(x,z),将这样的具有最小性的关系集合就是传递闭包。还有解释:传递闭包、即在数学中,在集合 X 上的二元关系 R 的传递闭包是包含 R 的 X 上的最小的传递关系。例如,如果 X 是(生或死)人的集合而 R 是关系"为父子",则 R 的传递闭包是关系"x 是 y 的祖先"。再比如,如果 X 是空港的集合而关系 xRy 为"从空港 x 到空港 y 有直航",则 R 的传递闭包是"可能经一次或多次航行从 x 飞到 y"。

这道题我们可以在X集(编号集合)上定义关系“赢”,则该关系是满足传递性的。可以用floyd求解传递闭包,传递闭包的传递公式是:dis[i][j]=dis[i][j]|(dis[i][k]&dis[k][j]) ,这道题唯一的注意点就是三重循环中的一个小优化。

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x7ffffff
20 inline int read(){
21     int ans=0,w=1;
22     char ch=getchar();
23     while(!isdigit(ch)){if(ch==-)w=-1;ch=getchar();}
24     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-0,ch=getchar();
25     return ans*w;
26 }
27 const int maxn=1000;
28 int n,m,t;
29 int dis[maxn][maxn];
30 void floyd()
31 {
32     f(k,1,n)
33         f(i,1,n)
34         {
35             if(dis[i][k])
36             f(j,1,n)
37             {
38                 dis[i][j]=dis[i][j]|(dis[i][k]&dis[k][j]);//传递闭包 
39              } 
40         }    
41             
42  } 
43  int ans=0;
44 int main()
45 {
46     //freopen("input.txt","r",stdin);
47     //freopen("output.txt","w",stdout);
48     std::ios::sync_with_stdio(false);
49     t=read();
50     while(t--)
51     {
52         mem(dis,0);
53         ans=0;
54         n=read(),m=read();
55         int x,y;
56         while(m--)
57         {
58             x=read(),y=read();
59             dis[x][y]=1;
60         }
61         floyd();
62         f(i,1,n)
63             f(j,i+1,n)
64             {
65                 if(!dis[i][j]&&!dis[j][i])ans++;//(i,j)之间没有关联,也就是不能推断出有输赢关系 
66             }
67             pf("%d
",ans) ;
68      } 
69 } 

 

以上是关于二元关系的关系的闭包的主要内容,如果未能解决你的问题,请参考以下文章

hdu1704传递闭包

二元关系

将三元关系分解为二元关系

离散数学二元关系的传递性该怎么去判定

集合论(基础+二元关系+函数)

浅谈传递闭包问题