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
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 }