题目链接
正权回路:在这一条路上,顶点的权值能不断的增加,即能一直进行松弛
由这个我们能想到Bellman-frod算法,他可以判断是否有负环
所以我们利用Bellman-frod算法的优化版本SPFA算法来解这道题
这里求的是能松弛的最大正权路径
A->B的权值就:(当前拥有的A的货币数量-损耗的货币数量)*转换比例;
初始化dis[s]=v,原点到其他点的路径的权值初始化为0,当s到其他某点的距离能不断变大的时候说明存在最大路径
#include<iostream>
#include<queue>
using namespace std;
#define N 1010
int n, m, s;
double v;
double map[N][N], cost[N][N], dis[N];
int vis[N];
int spfa(int x)
{
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
dis[x] = v;//将原点s的权值设为v
queue<int>q;//队列优化Belloman-Frod算法
q.push(x);
vis[x] = 1;
while (!q.empty())
{
int front1 = q.front();//取队首元素,通过队首元素进行松弛
q.pop();
vis[front1] = 0;
for (int i = 0; i <= n; i++)
{
if (dis[i] < (dis[front1] - cost[front1][i]) * map[front1][i])//如果原点到i的的权值小于通过队首元素松弛的大小
{
dis[i] = (dis[front1] - cost[front1][i]) * map[front1][i];//是原点到i的权值增加
if (dis[x] > v)//如果原点的权值比v大的时候说明存在正权回路
{
return 1;
}
if (!vis[i])//如果当前点不在队列中将当前点添加到队列当中
{
q.push(i);
vis[i] = 1;
}
}
}
}
return 0;
}
int main()
{
while (scanf("%d%d%d%lf", &n, &m, &s, &v) != EOF)
{
for (int i = 1; i <= n; i++)//常规初始化
{
for (int j = 1; j <= n; j++)
{
if (i == j)
{
map[i][j] = 1;
}
else
{
map[i][j] = 0;
}
cost[i][j] = 0;
}
}
int a, b;
double rab, crab, rba, crba;
for (int i = 0; i < m; i++)
{
cin >> a >> b >> rab >> crab >> rba >> crba;
map[a][b] = rab;
cost[a][b] = crab;
map[b][a] = rba;
cost[b][a] = crba;
}
if (spfa(s))//判断是否存在正权回路
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}