题意:
。。。
思路:
先将所有输入w取反,表示消耗,SPFA中记录每个点入队次数,若v入队次数>n,表示存在负环,则记d[v]=-inf,且不再入队
代码:
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int MAX_N=1000000;
int n;
struct edge
{
int u,to,next,cost;
}e[MAX_N];
int p[MAX_N],eid=0;
void init()
{
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int w)
{
e[eid].to=v;
e[eid].cost=w;
e[eid].next=p[u];
p[u]=eid++;
}
bool inq[MAX_N];
int cnt[MAX_N];
int d[MAX_N]; // 如果到顶点 i 的距离是 0x3f3f3f3f,则说明不存在源点到 i 的最短路
void spfa(int s)
{
memset(inq, 0, sizeof(inq));
memset(d, 0x3f, sizeof(d));
memset(cnt,0,sizeof(cnt));
int heal=100;
d[s] = 0;
inq[s] = true;
cnt[s]=1;
queue<int> q;
q.push(s);
while (!q.empty())
{
for(int i=1;i<=n;i++) //入队次数超过n,表示存在负环,将其d改为-inf,不再入队
{
if(cnt[i]>n)
d[i]=-1000000;
}
int u = q.front();
q.pop();
inq[u] = false;
for (int i = p[u]; i != -1; i = e[i].next) {
int v = e[i].to;
if (d[u] + e[i].cost < d[v]) {
d[v] = d[u] + e[i].cost;
if (!inq[v] && cnt[v]<n) //入队次数超过n表示有环,不再入队
{
q.push(v);
cnt[v]++;
inq[v] = true;
}
}
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
init();
cin>>n;
for(int i=1;i<=n;i++)
{
int w,m,v;
cin>>w>>m;
for(int j=0;j<m;j++)
{
cin>>v;
insert(i,v,-w); //w取反表示消耗
}
}
spfa(1);
if(100-d[n]>0)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
return 0;
}