POJ 1932 XYZZY (ZOJ 1935)SPFA+floyd

来源:互联网 发布:天天模拟器电脑版淘宝 编辑:程序博客网 时间:2024/04/29 19:57

http://poj.org/problem?id=1932

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1935


题目大意:

看到XYZZY可不要以为是在玩扫雷哦。

给你一张图,初始你在房间1,初始生命值为100,进入每个房间会加上那个房间的生命(可能为负),要你进入房间n,问是否可能。(要求进入每个房间后生命值都大于0)

思路:

1、SPFA求最长路径,如果路径存在(即无环),那么肯定可以。

2、存在负环,不管她,因为如果为负,那就失败了。

3、存在正环,那么说明有无限生命((╯‵□′)╯︵┻━┻ 开挂啊,快举报!),不过无限生命也要求你可达n(我WA了就是因为这个!)

那么如何判断存在环?

用SPFA中,如果一个点入队超过n次,说明存在环。 - -|||


#include<cstdio>#include<cstring>#include<queue>using namespace std;const int INF=-9999999;const int MAXN=111;//注孤 - -|||bool map[MAXN][MAXN];int val[MAXN],dis[MAXN];int n;bool SPFA(){for(int i=1;i<=n;i++)dis[i]=INF;bool vis[MAXN]={0};int cnt[MAXN]={0};queue<int> q;q.push(1);vis[1]=true;dis[1]=100;cnt[1]=1;while(!q.empty()){int cur=q.front();q.pop();if(cnt[cur] > n)break;vis[cur]=false;for(int i=1;i<=n;i++){if(map[cur][i]==true && dis[cur] + val[i] > dis[i]&& dis[cur] + val[i] > 0 ){dis[i]=dis[cur] + val[i];if(!vis[i]){q.push(i);vis[i]=true;cnt[i]++;}}}}if(dis[n]>0)return true;else {for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(map[i][k] && map[k][j])map[i][j]=true;for(int i=1;i<=n;i++)if(cnt[i]>n && map[1][i] && map[i][n]) //忘记要从i到N了return true;return false;}}int main(){while(~scanf("%d",&n),n!=-1){memset(map,0,sizeof(map));memset(val,0,sizeof(val));for(int i=1;i<=n;i++){int cnt,temp;scanf("%d %d",&val[i],&cnt);for(int j=1;j<=cnt;j++){scanf("%d",&temp);map[i][temp]=true;}}if(SPFA())puts("winnable");elseputs("hopeless");}return 0;}


4 0