如何求最小依赖集?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何求最小依赖集?相关的知识,希望对你有一定的参考价值。
在百度里看到这样一道题:
R(U, F),U=ABCDEF, F=AD→E, AC→E, BC→F, BCD→AF, BD→A, AB→F, A→C求最小函数依赖集
答案是:
分解右部为属性组的函数依赖,得
F=AD→E,AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C
对于AD→E,∵(AD)的闭包=ADCE, 又∵E不属于ACDE
∴AD→E 冗余
对于AC→E,∵(AC)的闭包=AC,又∵E不属于AC,∴AC→E不冗余
对于BC→F,∵(BC)的闭包=BC,又∵F不属于BC,∴BC→F 不冗余
对于BCD→A,∵(BCD)的闭包=ABCDEF,又∵A不属于ABCDEF ∴BCD→A 冗余
对于BCD→F,∵(BCD)的闭包=ABCDEF,又∵F不属于ABCDEF ∴BCD→F 冗余
对于BD→A,∵(BD)的闭包=BD,又∵A不属于BD,∴BD→A 不冗余
对于AB→F,∵(AB)的闭包=ABCDEF,又∵F属于ABCDEF ∵AB→F 冗余
对于A→C,∵A的闭包=A,又∵C不属于A,∴A→C 不冗余
∴F的最小函数依赖集为AC→E,BC→F,BD→A,A→C
谁能帮忙解释一下?我有些看不懂,什么叫闭包?怎么知道冗余不冗余?谢谢!!我比较笨,呵呵!!
将f中的所有依赖右边化为单一元素
adg->bc
==>adg->b,
adg->c
f'=b->d,
dg->c,
bd->e,
ag->b,
adg->b,
adg->c
2.
去掉f中的所有依赖左边的冗余属性.
3.
去掉f中所有冗余依赖关系. 参考技术B 这个题 应该是:
F=AD→E,AC→E,BC→F,BCD→A,BCD→F,BD→A,AB→F,A→C
对于AD→E,∵(AD)的闭包=ADCE, 又∵ACDE 包含E
∴AD→E 冗余
对于AC→E,∵(AC)的闭包=AC,又∵AC不包含E,∴AC→E不冗余
对于BC→F,∵(BC)的闭包=BC,又∵BC不包含F,∴BC→F 不冗余
对于BCD→A,∵(BCD)的闭包=ABCDEF,又∵ABCDEF包含A ∴BCD→A 冗余
对于BCD→F,∵(BCD)的闭包=ABCDEF,又∵ABCDEF包含F ∴BCD→F 冗余
对于BD→A,∵(BD)的闭包=BD,又∵BD不包含A,∴BD→A 不冗余
对于AB→F,∵(AB)的闭包=ABCDEF,又∵ABCDEF包含F ∵AB→F 冗余
对于A→C,∵A的闭包=A,又∵A不包含C,∴A→C 不冗余
∴F的最小函数依赖集为AC→E,BC→F,BD→A,A→C
例:
对于AD→E,∵(AD)的闭包=ADCE, 又∵E不属于ACDE
∴AD→E 冗余
闭包是指AD在R中的其它关系,有没有AD的子集函数依赖,依次找出来。
AD所包含的依赖关系有可能的组合是A,D,AD
在R中找出,并展开,
在R中能找到的关系是:A→C,没有找到D,AD所被依赖的关系。
所以AD'+的闭包:ADC。
继续找ADC->E的闭包,找A,D,C,AD,AC,DC ,得到AC->E
所以ADC'+的闭包为ADCE,
再继续分解找ADCE'+ ,得于ADCE.
所以最终的闭包为ADCE, 所包含E ,所以说AD->E是多余的。
其它的R的关系 可以按此方法判断。本回答被提问者采纳
思维dfs树/求最小环——cf 1364D
这题的强化版 1325F
题目里很友好的给了一个结论:对于任何一张n个点的无向图,任何一个k<=n,图中要么有大小不超过k的环,要么有大小为ceil(k/2)的独立集
证明很简单:
我们先定义单元环:环上的点的度数都为2
对于任意一个单元环,其大小如果超过k,那么必有>=ceil(k/2)的独立集
然后考虑如何求任意一个这样的单元环:bfs时只要碰到的第一个环就是单元环,我们把这个单元环取出来判一下就行
/* 图中的最小环,如果环大小>k,说明环中必定存在ceil(k/2)的独立集 */ #include<bits/stdc++.h> using namespace std; #define N 200005 int n,m,k,pre[N],vis[N]; vector<int>G[N],cir; void reverse(vector<int>&v){ int i=0,j=v.size()-1; while(i<j) swap(v[i],v[j]),++i,--j; } void bfs(){ for(int i=1;i<=n;i++)vis[i]=-1; queue<int>q; q.push(1); vis[1]=1;pre[1]=1; while(q.size()){ int u=q.front();q.pop(); for(auto v:G[u])if(v!=pre[u]){ if(vis[v]==-1){ vis[v]=vis[u]^1; q.push(v); pre[v]=u; } else {//出现环了 vector<int>v1,v2; int t=v; v1.push_back(t); while(pre[t]!=t) v1.push_back(pre[t]),t=pre[t]; t=u; v2.push_back(t); while(pre[t]!=t) v2.push_back(pre[t]),t=pre[t]; reverse(v1); reverse(v2); //for(auto x:v2)cout<<x<<" "; int i; vector<int>s; for(i=0;i<v1.size()&&i<v2.size();i++) if(v1[i]!=v2[i])break; i--; for(int j=i;j<v1.size();j++) s.push_back(v1[j]); for(int j=v2.size()-1;j>i;j--) s.push_back(v2[j]); if(s.size()<=k){//环<=k cout<<2<<‘ ‘<<s.size()<<‘ ‘; for(auto x:s)cout<<x<<‘ ‘; return; } vector<int>s1,s0;//独立集 for(auto x:s){ if(vis[x]==0)s0.push_back(x); else s1.push_back(x); } if(s1.size()>s0.size())swap(s1,s0); cout<<1<<" "; for(int i=0;i<ceil(1.0*k/2);i++) cout<<s1[i]<<" "; return; } } } //是个无环图输出独立集即可 vector<int>s1,s0; for(int x=1;x<=n;x++){ if(vis[x]==0)s0.push_back(x); else s1.push_back(x); } if(s1.size()<s0.size())swap(s1,s0); cout<<1<<" "; for(int i=0;i<ceil(1.0*k/2);i++) cout<<s1[i]<<" "; return; } int main(){ cin>>n>>m>>k; for(int i=1;i<=m;i++){ int u,v;scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } bfs(); }
以上是关于如何求最小依赖集?的主要内容,如果未能解决你的问题,请参考以下文章
数据库系统方面的问题,求最小函数依赖集、候选码、分解满足范式的关系模式