如何求最小依赖集?

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
谁能帮忙解释一下?我有些看不懂,什么叫闭包?怎么知道冗余不冗余?谢谢!!我比较笨,呵呵!!

参考技术A 求最小函数依赖集分三步:
将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();
}

 

以上是关于如何求最小依赖集?的主要内容,如果未能解决你的问题,请参考以下文章

求最小函数依赖集

数据库系统方面的问题,求最小函数依赖集、候选码、分解满足范式的关系模式

数据库求闭包,求最小函数依赖集,求候选码,判断模式分解是否为无损连接,3NF,BCNF

数据库怎样求最小函数依赖集,候选码,分解bcnf例题

找到给定函数依赖集的最小覆盖

如何从功能依赖中获取最小密钥?