(1)题意:
起点为1,起点的初始能量为100,每通过一条路径到达一个点,如果到达这一点的能量大于0,才可以到达这一点,
否则不行,问能否到达n点(是有向图)。
输入一个n,接下来n行,每行x表示能量,y表示与这个点相连的单向边的数量,然后输入y个点。
如果n=-1,结束输入。
(2)思路:
记录每个点访问的次数,如果次数是n+1就说明这是一个正数环,然后改变这个点的值,变为INF,
如果访问到n+2次,说明这个点的影响已经传递到它的子节点上了,所以跳出正数环即可。
(3)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1e5+10;
const int INF = 1e9+10;
int vis[maxn],dis[maxn],n,tim[maxn],mp[220][220];
struct Node{
int v,nxt,w;
}cur[maxn];
void Init(){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) mp[i][j] = -INF;
}
bool spfa(){
for(int i=0;i<=n;i++){
vis[i] = tim[i] = 0;dis[i] = -INF;
}
dis[1] = 100;
queue <int> q;
q.push(1);
while(!q.empty()){
int x = q.front();q.pop();vis[x] = 0;
tim[x]++;
if(tim[x]==n+1) dis[x] = maxn;
if(tim[x]==n+2) continue;
for(int i=1;i<=n;i++)
if(mp[x][i]!=-INF&&dis[i]<dis[x]+mp[x][i]&&dis[x]+mp[x][i]>0){
dis[i] = dis[x]+mp[x][i];
if(dis[n]>0) return true;
if(vis[i]==0){
vis[i] = 1;
q.push(i);
}
}
}
return false;
}
int main(void){
while(~scanf("%d",&n)&&n!=-1){
Init();
for(int i=1;i<=n;i++){
int x,y;scanf("%d%d",&x,&y);
for(int j=1;j<=y;j++){
int t;scanf("%d",&t);
mp[i][t] = x;
}
}
if(n==1){
printf("winnable\n");
continue;
}
if(spfa()==true) printf("winnable\n");
else printf("hopeless\n");
}
return 0;
}