题意:有N个房间,刚开始你位于1号房间,有100的能量值,你要到达N号房间,每两个房间之间有单向门相连接,你到达某个房间可以加上该房间的能量值,
如果你在未到达N号房间之前能量值耗尽,则死亡,否则胜利。
解析:spfa,设power[]是从1到达某个点的能量值,如果power[v]<power[u]+energy[v],(power[1]设置为100,其他设置为0)则更新,所以power[]
不会出现负数的情况,由于可能出现环的情况,所以要设置spfa次数上限,我设的10000,应该足够了,设置小了会wa。可以自己尝试一下。
代码如下:
#include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #include<iterator> #include<utility> #include<sstream> #include<iostream> #include<cmath> #include<stack> using namespace std; const int INF=1000000007; const double eps=0.00000001; vector<int> G[105]; int N; int energy[105],power[105]; // energy是房间的能量值,power是从1到达某个房间的能量值 bool vis[105]; int cnt[105]; // 访问次数 bool spfa() { memset(vis,false,sizeof(vis)); memset(power,0,sizeof(power)); memset(cnt,0,sizeof(cnt)); power[1]=100; vis[1]=true; queue<int> que; que.push(1); while(!que.empty()) { int now=que.front(); que.pop(); vis[now]=false; for(int i=0;i<G[now].size();i++) { int to=G[now][i]; if(power[now]+energy[to]>power[to]&&cnt[to]<=10000) // 次数上限为10000 { power[to]=power[now]+energy[to]; // 更新 cnt[to]++; if(!vis[to]) { vis[to]=true; que.push(to); } } } if(power[N]>0) return true; //为真 } return false; } int main() { while(cin>>N) { if(N==-1) break; for(int i=0;i<=N;i++) G[i].clear(); for(int i=1;i<=N;i++) { int k; scanf("%d%d",&energy[i],&k); for(int j=1;j<=k;j++) { int to; scanf("%d",&to); G[i].push_back(to); } } if(spfa()) printf("winnable "); else printf("hopeless "); } return 0; }