/* 题意:从1走到n,每走到一个屋子即可获得屋里的能量。 能量值可为负,问是否可以走到n 思路: 题目实际是求从起点到终点的最长路径问题 由于没到一个点,能量值不为负,所以使用d[]来记录到各点后的能量值 ,初始化为0,然后使用循环进行松弛,最后判断d[n]是否大于零,如果 是则可达。但是如果图中出现正环,则可能使程序陷入死循环,则不要 在出现正环时能跳出循环。 另外,在之前需要进行一次初始化,从n开始进行逆向搜索,判断各点 是否能到达n(这一步必不可少,若在不可达的点集中出现一个环则会出错) ,然后使用队列优先的Bellman-Ford算法即可 */ #include <cstdio> #include <cstring> const int nMax=110; int G[nMax][nMax],w[nMax],d[nMax]; int q[nMax],inq[nMax],inedq[nMax]; int visit[nMax],reach[nMax]; int n; void dfs(int u) { visit[u]=1; reach[u]=1; for(int v=1;v<=n;v++) { if(G[v][u] && !visit[v]) { dfs(v); } } } int main() { //freopen("data.in","r",stdin); while(scanf("%d",&n)==1) { if(n==-1) break; memset(G,0,sizeof(G)); memset(w,0,sizeof(w)); for(int i=1;i<=n;i++) { scanf("%d",&w[i]); int k; scanf("%d",&k); for(int j=0;j<k;j++) { int u; scanf("%d",&u); G[i][u]=1; } } memset(visit,0,sizeof(visit)); memset(reach,0,sizeof(reach)); dfs(n); if(!reach[1]) { printf("hopeless\n"); continue; } int front=0,rear=0; memset(q,0,sizeof(q)); memset(d,0,sizeof(d)); memset(inq,0,sizeof(inq)); memset(inedq,0,sizeof(inedq)); q[front++]=1; d[1]=100; inq[1]=1; inedq[1]++; bool ok=false; while(front!=rear) { int u=q[rear++]; if(rear==n) rear=0; inq[u]=0; for(int v=1;v<=n;v++) { if(G[u][v] && reach[v] && d[u]+w[v]>d[v]) { d[v]=d[u]+w[v]; if(!inq[v]) { q[front++]=v; if(front==n) front=0; inq[v]=1; inedq[v]++; if(inedq[v]>n) { ok=true; break; } } } } if(d[n]>0 || ok) break; } if(d[n]>0 || ok) printf("winnable\n"); else printf("hopeless\n"); } return 0; }