BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)

Description

传说中,有个神奇的潘多拉宝盒。如果谁能打开,便可以拥有幸福、财富、爱情。可是直到真的打开,才发现与之
相随的还有灾难、不幸。其实,在潘多拉制造这个宝盒的时候,设置了一些咒语来封锁住灾难与不幸。然而,直到
科技高度发达的今天,人们才有希望弄懂这些咒语。所以说,上千年来,人们只得忍受着各种各样的疾病和死亡的
痛苦。然而,人类的命运从此改变了。经过数十年的研究,NOI组织在最近终于弄清楚了潘多拉咒语的原理。咒语
是由一个叫做咒语机的机器产生的。用现在的名词来解释,咒语机其实就是一个二进制产生器,它产生的一个二进
制字符串(这个字符串叫做咒语源)经加密后就形成了咒语。二进制产生器的结构是这样的:它由n个元件组成,
不妨设这n个元件的标号为0到n-1。在每个时刻,都有且仅有一个信号,它停留在某个元件上。一个信号就是一个
二进制字符串。最开始,有一个空串信号停留在元件0上。在某个时刻,如果有一个信号s停留在元件I上,那么,
这时元件i可以将信号后面加一个0,然后把信号传给元件pi,0,也可以将信号后面加一个1,然后传给元件pi,1。也
就是说,下一个时刻有可能,一种可能是一个信号S0(表示字串S后面加一个0形成的字串)仪在元件pi,0上,另一
种可能是有一个信号S1停留在元件pi,1上。有的元件可以将停留在它上面的信号输出,而输出的信号就成为了咒语
源,这样的元件叫做咒语源输出元。不难发现,有些口语源是可能由一个咒语机产生的,而另一些咒语源则不行。
例如,下图的咒语机能产生1,11,111,1111,...等咒语源,但是不能产生0,10,101等咒语源。在这个盒子上,有K个
咒语机,不妨将这些咒语机从0到K-1标号。可能有这种情况,一个咒语机i能够产生的口语源,咒语机j都能产生。
这时,我们称咒语机j是咒语机i的升级。而衡量这个例子的复杂程度的一种办法是:看这个盒子上升级次数最多的
一个咒语机。即:找到一个最长的升级序列a1,a2...at。该升级序列满足:序列中任意两个咒语机的标号都不同,
且都是0到k-1(包含0和k-1)之间的整数,且咒语机a2是咒语机a1的升级,咒语机a3是咒语机a2的升级...,咒语
机at是咒语机at-1的升级。你想远离灾难与不幸吗?你想从今以后沐浴幸福的阳光吗?请打开你的潘多拉之盒吧。
不过在拱形它之前,你先得计算一下宝盒上最长的升级序列。

Input

第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50)。
文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1...咒语机S-1的顺序描述。
每一块的格式如下。 
一块的第一行有两个正整数n,m。分别表示该咒语机中元件的个数、咒语源输出元的个数
(1≤m≤n≤50)。 
接下来一行有m个数,表示m个咒语源输出元的标号(都在0到n-1之间)。
接下来有n行,每一行两个数。第i行(0≤i≤n-1)的两个数表示pi,0和pi,1
(当然,都在0到n-1之间)。

Output

第一行有一个正整数t,表示最长升级序列的长度。

Sample Input

4
1 1
0
0 0
2 1
0
1 1
0 0
3 1
0
1 1
2 2
0 0
4 1
0
1 1
2 2
3 3
0 0

Sample Output

3

解题思路:

考虑升级关系的判定。
枚举两个图。
由于这个图的特殊性,那就是永远不会失配。
那么我们就只需要判定输出位置就好了。
由于具有高度循环性,只需要Bfs一遍判断就好了。
最后判断包含关系,很显然图中具有传递性
而传递回来只能说明图之间等价。
那么就tarjan缩点跑个Dp就好了。
代码:
  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 struct Pr_ma{
  6     struct pnt_{
  7         int ch[2];
  8         bool out;
  9     }p[100];
 10     int n,m;
 11     int can;
 12     int f;
 13     void Insert(void)
 14     {
 15         scanf("%d%d",&n,&m);
 16         for(int i=1;i<=m;i++)
 17         {
 18             int id;
 19             scanf("%d",&id);
 20             p[id].out=true;
 21         }
 22         for(int i=0;i<n;i++)
 23             scanf("%d%d",&p[i].ch[0],&p[i].ch[1]);
 24         return ;
 25     }
 26 }pr[51];
 27 struct pnt{
 28     int hd;
 29     int dfn;
 30     int low;
 31     int blg;
 32     bool vis;
 33     void res(int x)
 34     {
 35         dfn=low=x;
 36         return ;
 37     }
 38 }p[100];
 39 struct pnt_{
 40     int hd;
 41     int wgt;
 42     int ind;
 43 }p_[100];
 44 struct ent{
 45     int twd;
 46     int lst;
 47 }e[10000],e_[10000];
 48 struct int_{int x;int y;};
 49 int n;
 50 int cnt;
 51 int s_t;
 52 int c_t;
 53 int stt;
 54 int col;
 55 int cnt_;
 56 int dp[100000];
 57 int sta[100000];
 58 int_ stack_[100000];
 59 bool vis[100][100];
 60 std::queue<int>Q;
 61 std::queue<int_>Q_;
 62 void ade(int f,int t)
 63 {
 64     cnt++;
 65     e[cnt].twd=t;
 66     e[cnt].lst=p[f].hd;
 67     p[f].hd=cnt;
 68     return ;
 69 }
 70 void ade_(int f_,int t_)
 71 {
 72     cnt_++;
 73     e_[cnt_].twd=t_;
 74     e_[cnt_].lst=p_[f_].hd;
 75     p_[f_].hd=cnt_;
 76     p_[t_].ind++;
 77     return ;
 78 }
 79 bool Bfs(Pr_ma x_,Pr_ma y_)
 80 {
 81     while(!Q_.empty())Q_.pop();
 82     memset(vis,0,sizeof(vis));
 83     Q_.push(stack_[0]);
 84     while(!Q_.empty())
 85     {
 86         int_ h=Q_.front();Q_.pop();
 87         if(vis[h.x][h.y])continue;
 88         vis[h.x][h.y]=true;
 89         stack_[++s_t]=h;
 90         if(x_.p[h.x].out&&!y_.p[h.y].out)return false;
 91         int nx,ny;
 92         for(int c=0;c<2;c++)
 93         {
 94             nx=x_.p[h.x].ch[c];
 95             ny=y_.p[h.y].ch[c];
 96             Q_.push((int_){nx,ny});
 97         }
 98     }
 99     return true;
100 }
101 void tarjan(int x)
102 {
103     p[x].vis=true;
104     sta[++stt]=x;
105     p[x].res(++c_t);
106     for(int i=p[x].hd;i;i=e[i].lst)
107     {
108         int to=e[i].twd;
109         if(p[to].dfn&&!p[to].blg)
110             p[x].low=std::min(p[x].low,p[to].dfn);
111         else if(!p[to].dfn)
112         {
113             tarjan(to);
114             p[x].low=std::min(p[x].low,p[to].low);
115         }
116     }
117     if(p[x].dfn==p[x].low)
118     {
119         col++;
120         int u;
121         do{
122             p_[col].wgt++;
123             u=sta[stt--];
124             p[u].blg=col;
125         }while(u!=x);
126     }
127     return ;
128 }
129 int Top_sort(void)
130 {
131     while(!Q.empty())Q.pop();
132     int ans=0;
133     for(int i=1;i<=col;i++)if(!p_[i].ind)
134         Q.push(i);
135     while(!Q.empty())
136     {
137         int x=Q.front();Q.pop();
138         dp[x]+=p_[x].wgt;
139         for(int i=p_[x].hd;i;i=e_[i].lst)
140         {
141             int to=e_[i].twd;
142             p_[to].ind--;
143             dp[to]=std::max(dp[to],dp[x]);
144             if(!p_[to].ind)Q.push(to);
145         }
146         ans=std::max(ans,dp[x]);
147     }
148     return ans;
149 }
150 int main()
151 {
152 //    freopen("pandora.in","r",stdin);
153 //    freopen("pandora.out","w",stdout);
154     scanf("%d",&n);
155     for(int i=1;i<=n;i++)pr[i].Insert();
156     for(int i=1,j;i<=n;i++)for(j=1;j<=n;j++)if(i!=j)
157         if(Bfs(pr[i],pr[j]))ade(i,j);
158     for(int i=1;i<=n;i++)if(!p[i].blg)
159         tarjan(i);
160 //    for(int i=1;i<=n;i++)printf("%d\n",p[i].blg);
161     for(int u=1;u<=n;u++)
162     {
163         for(int i=p[u].hd;i;i=e[i].lst)
164         {
165             int v=e[i].twd;
166             int x=p[u].blg;
167             int y=p[v].blg;
168             if(x!=y)ade_(x,y);
169         }
170     }
171     printf("%d\n",Top_sort());
172     return 0;
173 }

 

posted @ 2019-01-22 23:01  Unstoppable728  阅读(530)  评论(0编辑  收藏  举报