#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
//#define DEBUG
struct exchgpnt
{
int a;
int b;
double rab;
double cab;
};
static struct exchgpnt edges[100 * 2];
static int m, n, s;
static double v;
static double dst[101];
int bellman_ford(int edgenum)
{
int i, j;
memset(dst, 0, sizeof dst);
dst[s] = v;
for (i = 1; i < n; i++) /* relax edges */
{
for (j = 0; j < edgenum; j++)
{
int a, b;
double rab, cab;
a = edges[j].a;
b = edges[j].b;
rab = edges[j].rab;
cab = edges[j].cab;
if (dst[a] == 0.0) continue; /* 加上这句后运行时间减半 */
if (dst[b] < (dst[a] - cab) * rab)
{
if (b == s) return 1; /* 存在正向回路 */
dst[b] = (dst[a] - cab) * rab;
}
}
}
for (j = 0; j < edgenum; j++)
{
int a, b;
double rab, cab;
a = edges[j].a;
b = edges[j].b;
rab = edges[j].rab;
cab = edges[j].cab;
if (dst[b] < (dst[a] - cab) * rab)
{
return 1; /* 存在正向回路 */
}
}
return 0;
}
int main()
{
#ifdef DEBUG
fstream cin("G:\\book\\algorithms\\acm\\Debug\\dat.txt");
#endif
while (cin >> n >> m >> s >> v)
{
int i, p;
for (p = i = 0; i < m; i++)
{
int a, b;
double rab, rba, cab, cba;
//cin >> a >> b >> rab >> cab >> rba >> cba;
/* 采用下面的输入方式时间减到0MS */
scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba);
edges[p].a = a; edges[p].b = b;
edges[p].cab = cab, edges[p++].rab = rab;
edges[p].a = b; edges[p].b = a;
edges[p].cab = cba, edges[p++].rab = rba;
}
if (bellman_ford(p))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
n种货币看成n个顶点,货币之间的转换就是顶点之间的边。这样输入数据就构成了一张图,问在图中是否存在从s------>s的正权回路。
就是s货币经过若干次兑换之后再换回s货币,数量会增加。基本思想和最短路径中的bellman_ford算法相同。bellman_ford算法以边
为输入。通过对全部的边做Relax操作n-1次,如果图中不存在负权回路,就能够得到从源点s到其他节点的最短路径的值。如果存在负
权回路,可以发现。