POJ 1932 XYZZY
問題
N部屋個の部屋があり、それらはいくつかの一方通行の通路で結ばれている。
各部屋にはそれぞれのエネルギーがあり、部屋に入る度に、自分の持っているエネルギーに部屋のエネルギーが足される。
部屋のエネルギーが負であることもある。
自分は最初100のエネルギーを持っており、そのエネルギーが0以下になると死んでしまう。
1番の部屋からN番の部屋へ到達できるかを判定せよ。
制約条件
N≦100
部屋のエネルギーの絶対値≦100
方針
ゴールの部屋からグラフを逆にたどり、「ゴールへ到達可能な頂点」を列挙しておく。
それ以外の頂点は捨ててよい。
グラフを頂点0から深さ優先探索していき、エネルギーが尽きずにゴールに行けるかを見る。
エネルギーを増加させるような閉路を途中で見つけた場合も、(そこでエネルギーを無限に増やせるので)ゴールへ到達可能である。
ソースコード
int n, v[100], cost[100]; vector<vi> g,rg; bool rv[100]; void rdfs(int c){ rv[c]=1; fr(i,rg[c])if(!rv[*i])rdfs(*i); } bool dfs(int c,int cc){ cc+=v[c]; if(cc<=0)return 0; if(c==n-1)return 1; if(cost[c]>=0){ if(cc>cost[c])return 1; return 0; } cost[c]=cc; fr(i,g[c])if(rv[*i]&&dfs(*i,cc))return 1; return 0; } int main() { while(scanf("%d",&n),~n){ g.clear();g.resize(n); rg.clear(); rg.resize(n); rep(i,n){ scanf("%d",v+i); int m; scanf("%d",&m); rep(j,m){ int t; scanf("%d",&t); t--; g[i].pb(t); rg[t].pb(i); } } rep(i,n)cost[i]=-inf, rv[i]=0; rdfs(n-1); puts(rv[0]&&dfs(0,100)?"winnable":"hopeless"); } return 0; }