题意是指 从1 到 N 能否保证 到达每个点的时候 能量都为正数。
起点 1 初始100 点能量。
输入是 从 1 ~ N , 分别是 能量,能到m个房间, 分别是 a1,a2,a3,…,am
可以给每个能到达的点 而 产生的边赋权,即能量值。
SPFA 求最长路的变形,出现负环不怕,出现正环就需要一点改动。
vis[]标记是否需要入队,d[] 表示能量,que[] 表示入队次数。
如果出现正环(que[v]>=n),表明一定能 保证到达每个点的时候都是正能量。
这时候直接 将 d[v] 赋最大值(因为可以一直循环获得正能量),并下一次的时候不再入队。
最后 d[n]>0 表明能行。
//C++ 0ms #include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<queue> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<cmath> #define INF 0xfffffff #define eps 1e-6 using namespace std; int n,m; struct lx { int v,en; }; vector<lx> g[101]; int d[101]; bool vis[101]; int que[101]; void SPFA() { for(int i=1; i<=n; i++) d[i]=-INF,vis[i]=0,que[i]=0; queue<int>q; d[1]=100,vis[1]=1,que[1]=1; q.push(1); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; if(que[u]>n)continue;// >= WA for(int j=0; j<g[u].size(); j++) { int v=g[u][j].v; int en=g[u][j].en; if(d[v]<d[u]+en&&d[u]+en>0) { d[v]=d[u]+en; if(!vis[v]) { vis[v]=1; q.push(v); if(++que[v]>=n)d[v]=INF; } } } } if(d[n]>0)puts("winnable"); else puts("hopeless"); } int main() { while(scanf("%d",&n),n!=-1) { int en,v,u; for(int i=0; i<=n; i++) g[i].clear(); for(int i=1; i<=n; i++) { u=i; scanf("%d%d",&en,&m); lx now; now.en=en; while(m--) { scanf("%d",&v); now.v=v; g[u].push_back(now); } } SPFA(); } }
时间: 2024-10-14 12:40:03