1. 程式人生 > >BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)

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

只需要 esc noi wid 之間 line 一個 分享 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 }

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