初始能量值为100,没走过一个房间加上该房间的能量值,问能否从起点到终点,能量值相当于边的权值,原问题等价于求2点之间的是否存在距离大于0,
难点在于存在正环,负环,参考了别人的处理方法1.存在正环时并且能到终点则win,否则按照普通的做法,2.spfa,为避免出现正环但不能到达终点的情况导致spfa死循环要设置一个最大的循环次数。
摘自http://blog.csdn.net/frankiller/article/details/7788259
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> using namespace std; int main() { //freopen("1.txt","r",stdin); int n; int energy[110],low[110],visit[110]; int map[110][110]; while(scanf("%d",&n)) { memset(map,0,sizeof(map)); if(n==-1)break; int i,j; for(i=1;i<=n;++i) { int m; scanf("%d%d",&energy[i],&m); for(j=1;j<=m;++j) { int k; scanf("%d",&k); map[i][k]=1; } } for(i=1;i<=n;++i) { visit[i]=1; low[i]=0;//low[i]表示到达第i个房间时的能量 } int m=0; int q[100]; int tou=0,wei=1; q[0]=1;low[1]=100; visit[1]=0; int f=0; while(wei!=tou) { if(m>1000000)break; for(i=1;i<=n;++i) { if(map[q[tou]][i]==1&&low[q[tou]]+energy[i]>low[i])//在不能直接就到达第n个房间的情况下,在正环中循环以获得足够能量,来到达第n个房间,而且肯定是到达下一个房间时能量增加,不会出现先减小后增加的情况,因为会从先减小后增加的方向走,否则永远不会到达第n个房间。 { low[i]=low[q[tou]]+energy[i]; if(visit[i]==1) { visit[i]=0;q[wei]=i; wei=(wei+1)%100;++m; } } } visit[q[tou]]=1; tou=(tou+1)%100; if(low[n]>0) { f=1;break; } } if(f)printf("winnable\n"); else printf("hopeless\n"); } return 0; }