AOJ 2011 Gather the Maps!
問題
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2011
解法
T日にスケジュールのあいている子孫の集合をCtとする
子孫cがT日に持っている地図の集合をMctとする
Mct = Mc(t-1) (c ∈ Ct でない)
∪{Md(t-1) | d ∈ Ct} (c ∈ Ct)
を計算していって、
始めてMctが地図全体の集合と等しくなるtを求めればよい
#include <cstdio> #include <algorithm> using namespace std; const int MAX_N = 50; const int DAY = 31; //a[i][j][d] 子孫iはt日の時点でjの持っていた地図を持つことが可能か bool dp[MAX_N][MAX_N][DAY+1]; //子孫のスケジュール bool a[MAX_N][DAY]; int main(){ int N; while(scanf("%d", &N) && N!=0 ){ for(int i=0;i<N;i++)for(int t=0;t<=DAY;t++) a[i][t] = false; for(int i=0;i<N;i++)for(int j=0;j<N;j++)for(int t=0;t<=DAY;t++){ dp[i][j][t] = (i==j); } for(int i=0;i<N;i++){ int f; scanf("%d", &f); for(int j=0; j<f; j++){ int d; scanf("%d", &d); a[i][d] = true; } } bool f; int t; for(t=1;t<=DAY;t++){ bool chi[N]; //t日にスケジュールのあいている子孫 bool m[N]; //地図 f = true; fill(chi, chi + N, false); fill(m, m + N, false); for(int i=0; i<N; i++){ chi[i] = a[i][t]; if(chi[i]){ for(int j=0; j<N; j++){ m[j] = m[j] || dp[i][j][t-1]; } } } for(int j=0;j<N;j++){ f=f&&m[j]; } if(f) break; for(int i=0; i<N; i++){ if(!chi[i]){ for(int j=0; j<N; j++) dp[i][j][t] = dp[i][j][t-1]; }else{ for(int j=0; j<N; j++) dp[i][j][t] = m[j]; } } } if(f && t <= 30){ printf("%d\n", t); }else printf("-1\n"); } return 0; }