注意,使用spfa算法的时候,一个点进队n+2次说明所有与其相关的点均已经得到了正环的收益,然而除此之外什么都不能说明,在这道题上,也就不可能说明此时某点的值是否可以大于它的初始值。spfa是个神奇的算法,的空一定要好好研究一番。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
struct Edge
{
int to,nex;
double c,r;
}edge[220];
int e,head[110],inq[110],vis[110],n,m,s;
double v,d[110];
void addedge(int a,int b,double rr,double cc)
{
edge[e].to=b;
edge[e].r=rr;
edge[e].c=cc;
edge[e].nex=head[a];
head[a]=e++;
//cout<<"a="<<a<<" b="<<b<<" r="<<rr<<" c="<<cc<<endl;
}
int spfa(int s)
{
queue<int> q;
memset(inq,0,sizeof(inq));
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
d[s]=v;
inq[s]=1;
q.push(s);
int tmp=s;
while (!q.empty())
{
s=q.front(); q.pop();
vis[s]++;
inq[s]=0;
//cout<<"s="<<s<<" vis="<<vis[s]<<endl;
if (d[tmp]>v) return true;
if (vis[s]==n+2) continue;
for (int i=head[s]; i!=-1; i=edge[i].nex)
{
int v=edge[i].to;
//cout<<"s="<<s<<" v="<<v<<" d="<<d[v]<<" d2="<<(d[s]-edge[i].c)*edge[i].r<<endl;
//cout<<"ds="<<d[s]<<" c="<<edge[i].c<<" r="<<edge[i].r<<endl;
if (d[v]<(d[s]-edge[i].c)*edge[i].r)
{
d[v]=(d[s]-edge[i].c)*edge[i].r;
if (!inq[v])
{
inq[v]=1; q.push(v);
}
}
//if (d[tmp]>v) return true;
}
}
return false;
}
int main()
{
while (~scanf("%d%d%d%lf",&n,&m,&s,&v))
{
e=0;
memset(head,-1,sizeof(head));
for (int i=1; i<=m; i++)
{
int a,b;
double rab,cab,rba,cba;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
addedge(a,b,rab,cab);
addedge(b,a,rba,cba);
}
if (spfa(s)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}