Wormholes(SPFA 判断负环)
题目poj3259
题目大意
给定F个农场,也就是N组样例。每组样例中给出n,m,w分别是点数,边数(双向,经过会消耗时间t),虫洞数(单向,经过会返回时间t)。
如果他能回到某点并且时间比之前到达这点要小,那么输出”YES"否则输出“NO”。
思路
如果是普通的路,那么时间就记为正的,如果是虫洞就记为负的。然后跑spfa。
在spfa中,如果经过一点的次数(也就是该点的入队次数)超过n,那么说明存在负环,输出yes,return。如果队列空了,就输出NO
#include <iostream>
#include <vector>
#include <queue>
#define N 1000
#define E 3000
#define INF 0x3f3f3f
using namespace std;
vector<pair<int, int>> eg[N];
queue<int> q;
int inq[N];
int d[N];
int n, m, w;
void init()
{
for (int i = 0; i <= n; i++)
inq[i] = 0;
for (int i = 0; i <= n; i++)
eg[i].clear();
for (int i = 0; i <= n; i++)
d[i] = INF;
}
void spfa()
{
q.push(0);
inq[0]++;
d[0] = 0;
while (!q.empty())
{
int now = q.front();
q.pop();
for (int i = 0; i < eg[now].size(); i++)
{
int v = eg[now][i].first;
if (d[v] > d[now] + eg[now][i].second)
{
d[v] = d[now] + eg[now][i].second;
//cout << now << " " << v << " " << d[v] << endl;
if (inq[v] > n)
{
cout << "YES" << endl;
return;
}
else
{
inq[v]++;
q.push(v);
}
}
}
}
cout << "NO" << endl;
}
int main()
{
int T, s, e, t;
cin >> T;
while (T--)
{
cin >> n >> m >> w;
init();
for (int i = 1; i <= m; i++)
{
cin >> s >> e >> t;
s--, e--;
eg[s].push_back(make_pair(e, t));
eg[e].push_back(make_pair(s, t));
}
for (int i = 1; i <= w; i++)
{
cin >> s >> e >> t;
s--, e--;
eg[s].push_back(make_pair(e, -t));
}
spfa();
}
}