bjoi 2009 函数依赖 强连通分量

对于30%的测试数据,满足只有二元联系(即不存在函数依赖左边或右边的
属性个数超过 1 个)。 
对于 40%的测试数据,满足N ≤ 5。 
对于 70%的测试数据,满足M ≤ 100。 
对于100%的测试数据,满足 1 ≤ N ≤ 10, 1 ≤ M ≤ 1000。

 

思路:因为n非常小

我们可以把2^n个关系全部列出来

按照题目的关系建立有向图

求强连通分量 缩点 拓扑排序

答案就是 某个节点自己在头节点中,而他的真子集都不在

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 using namespace std;
  7 #define MAXN (1<<10)+1
  8 #define MAXM 1<<22
  9 struct node
 10 {
 11     int num;
 12     node *next;
 13 };
 14 node *graph[MAXN],*grapht[MAXN],*graphnew[MAXN];
 15 node memo[MAXM];
 16 bool use[MAXN],visit[MAXN][MAXN];
 17 int finish[MAXN],cnt[MAXN],mark[MAXN],ans[MAXN];
 18 int n,m,top=0,t=0,sum=0,color=0;
 19 pair<int,int> a[MAXN];
 20 char c[30];
 21 bool cmp(int x,int y)
 22 {
 23     for(int i=0;i<11;i++)
 24     {
 25         if(((1<<i)&x)==(1<<i)&&((1<<i)&y)!=(1<<i))
 26             return 1;
 27         if(((1<<i)&x)!=(1<<i)&&((1<<i)&y)==(1<<i))
 28             return 0;
 29     }
 30 
 31 }
 32 void add(int x,int y,node *graph[])
 33 {
 34     node *p=&memo[top++];
 35     p->num=y; p->next=graph[x]; graph[x]=p;
 36 }
 37 void dfs(int i)
 38 {
 39     use[i]=1;
 40     for(node *p=graph[i];p;p=p->next)
 41         if(!use[p->num])
 42             dfs(p->num);
 43     finish[++t]=i;
 44 }
 45 void dfst(int i)
 46 {
 47     use[i]=1;
 48     mark[i]=color;
 49     cnt[color]++;
 50     for(node *p=grapht[i];p;p=p->next)
 51         if(!use[p->num])
 52             dfst(p->num);
 53 }
 54 
 55 void connect()
 56 {
 57     memset(use,0,sizeof(use));
 58     int i;
 59     for(i=1;i<n;i++)
 60         if(!use[i])
 61             dfs(i);
 62     memset(use,0,sizeof(use));
 63     for(i=t;i>0;i--)
 64     if(!use[finish[i]])
 65     {
 66         color++;
 67         dfst(finish[i]);
 68     }
 69 }
 70 void reduce()
 71 {
 72     memset(visit,0,sizeof(visit));
 73     int i;
 74     for(i=1;i<n;i++)
 75     for(node *p=graph[i];p;p=p->next)
 76     {
 77         if(visit[mark[i]][mark[p->num]]==0&&mark[i]!=mark[p->num])
 78         {
 79             visit[mark[i]][mark[p->num]]=1;
 80             add(mark[i],mark[p->num],graphnew);
 81         }
 82     }
 83 }
 84 void solve()
 85 {
 86     t=0;
 87     memset(ans,0,sizeof(ans));
 88     memset(use,0,sizeof(use));
 89     int i,j,k;
 90     for(i=1;i<n;i++)
 91     if(mark[i]==1)
 92     {
 93         for(j=1;j<n;j++)
 94             if((i&j)==j&&mark[j]==1&&i!=j)
 95                 break;
 96         if(j==n) 
 97             ans[++t]=i;
 98     }
 99     printf("%d\n",t);
100     sort(ans+1,ans+t+1,cmp);
101     for(i=1;i<=t;i++)
102     {
103         for(j=0;j<11;j++)
104             if((ans[i]&(1<<j))==(1<<j))
105                 printf("%c",('A'+j));
106         printf("\n");
107     }
108 }
109 
110 int main()
111 {
112     memset(visit,0,sizeof(visit));
113     memset(cnt,0,sizeof(cnt));
114     memset(graph,0,sizeof(graph));
115     memset(grapht,0,sizeof(grapht));
116     memset(graphnew,0,sizeof(graphnew));
117     memset(use,0,sizeof(use));
118     scanf("%d%d",&n,&m);
119     n=(1<<n);
120     int i,j,x,l,y,k;
121     for(i=1;i<=m;i++)
122     {
123         x=y=0;
124         scanf("%s",c);
125         l=strlen(c);
126         for(j=0;c[j]!='-';j++)
127             x=x|(1<<(c[j]-'A'));
128         j=j+2;
129         for(j;j<l;j++)
130             y=y|(1<<(c[j]-'A'));
131         a[i].first=x; a[i].second=y;
132     }
133     for(i=1;i<n;i++)
134         for(k=1;k<=m;k++)
135             if((i&a[k].first)==a[k].first)
136                 for(j=1;j<n;j++)
137                     if(((i|a[k].second)&j)==j)
138                         visit[i][j]=1;
139     for(i=1;i<n;i++)
140         for(j=1;j<n;j++)
141             if(visit[i][j])
142             {
143                 add(i,j,graph);
144                 add(j,i,grapht);
145             }
146 
147     connect();
148     reduce();
149     solve();
150     return 0;
151 }

 

原文地址:https://www.cnblogs.com/myoi/p/2494885.html