BZOJ1194: [HNOI2006]潘多拉的盒子(tarjan)
阿新 • • 發佈:2019-01-23
只需要 esc noi wid 之間 line 一個 分享 tarjan
不妨設這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的升級。你想遠離災難與不幸嗎?你想從今以後沐浴幸福的陽光嗎?請打開你的潘多拉之盒吧。
不過在拱形它之前,你先得計算一下寶盒上最長的升級序列。
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
Description
傳說中,有個神奇的潘多拉寶盒。如果誰能打開,便可以擁有幸福、財富、愛情。可是直到真的打開,才發現與之 相隨的還有災難、不幸。其實,在潘多拉制造這個寶盒的時候,設置了一些咒語來封鎖住災難與不幸。然而,直到 科技高度發達的今天,人們才有希望弄懂這些咒語。所以說,上千年來,人們只得忍受著各種各樣的疾病和死亡的 痛苦。然而,人類的命運從此改變了。經過數十年的研究,NOI組織在最近終於弄清楚了潘多拉咒語的原理。咒語 是由一個叫做咒語機的機器產生的。用現在的名詞來解釋,咒語機其實就是一個二進制產生器,它產生的一個二進 制字符串(這個字符串叫做咒語源)經加密後就形成了咒語。二進制產生器的結構是這樣的:它由n個元件組成,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
41 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)