版权声明:copy right https://blog.csdn.net/qq_43521140/article/details/91408087
SPFA它没死
Source
SPFA判正环好题
具体解释看注释:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define fuck cout << "fuck" << endl;
#define mem(a,b) memset(a,b,sizeof(a))
#define Fast ios::sync_with_stdio(false);
const int N = 2e2 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef long long ll;
struct Edge
{
int v,w,next;
} edge[N*N];
int cnt,head[N],n;
int vis[N],d[N],num[N];
void init()
{
cnt=0;
mem(head,-1);
}
void addedge(int u,int v,int w)
{
edge[cnt].v=v,edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
//spfa判正环
void spfa(int s)
{
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
for(int i = 1;i <= n;++i)
{
vis[i] = 0;
num[i] = 0;
}
//起点能量为100
for(int i=1; i<=n; i++)
d[i]=i==s?100:-INF;
vis[s]=1;
queue<int>que;
que.push(s);
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=0;
num[u]++;//入队次数加一
if(num[u]>n) d[u]=INF;//如果u是正环内的点 则能量值可以为INF
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v,w=edge[i].w;
if(d[u]+w>0&&d[v]<d[u]+w)//保证中途能量不为非正数
{
d[v]=d[u]+w;
//如果入队次数多于n就不入队了
//否则会死循环
if(!vis[v]&&num[v]<=n)
{
vis[v]=1;
que.push(v);
}
}
}
}
}
int main()
{
int e,m,t;
while(~scanf("%d",&n)&&n!=-1)
{
init();
for(int i=1; i<=n; i++)
{
scanf("%d %d",&e,&m);
while(m--)
{
scanf("%d",&t);
addedge(i,t,e);
}
}
spfa(1);
//如果能走到终点且最大能量大于0
if(d[n]>0) printf("winnable\n");
else printf("hopeless\n");
}
return 0;
}