POJ - 3259 Wormholes ~~spfa判断是否有负环
Wormholes
While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..N, M (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.
As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .
To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.
Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2.. M+1 of each farm: Three space-separated numbers ( S, E, T) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.
Lines M+2.. M+ W+1 of each farm: Three space-separated numbers ( S, E, T) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.
2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8Sample Output
NO YESHint
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.
就是让你看下~~主角是否能够通过穿越单向的虫洞(权值为负)来达到不断返回过去的情况~~建成图之后就是判定是否存在负环的存在问题~~
#include<cstdio>
#include<queue>
#include<iostream>
using namespace std;
int m, n;
int head[1000];//链式前向星
struct edge
{
int to;
int ne ;
int len;
}ed[10000];//储存边~~
int time[1000];//用来判断是否有负环
bool vis[1000];
int d[1000];//距离(在这里代表时间)
int cnt = 0;
void init()//初始化
{
for (int s = 0; s <= 999; s++)
{
head[s] = -1;
}
for (int s = 0; s <= n; s++)
{
d[s] = 999999;
}
for (int s = 0; s < 9000; s++)
{
ed[s].ne = -1;
}
memset(vis, 0, sizeof(vis));
memset(time, 0, sizeof(time));
}
void add(int from, int to, int len)
{
ed[cnt].to = to;
ed[cnt].len = len;
ed[cnt].ne = head[from];
head[from] = cnt++;
}
bool spfa()//返回是否能有负环
{
d[1] = 0;
queue<int>q;
q.push(1);
vis[1] = 1;
bool flag = false;
while (!q.empty())
{
int t = q.front();
q.pop();
// cout << t << endl;
// cout << head[t] << endl;
for (int s = head[t]; ~s; s = ed[s].ne)
{
// cout << t << " " << ed[s].to << endl;
if (d[ed[s].to] > d[t] + ed[s].len)
{
d[ed[s].to] = d[t] + ed[s].len;
if (!vis[ed[s].to])
{
// cout << ed[s].to << endl;
vis[ed[s].to] = 1;
time[ed[s].to]++;
if (time[ed[s].to] > n)
{
flag = true;
return flag;
}
q.push(ed[s].to);
}
}
}
vis[t] = 0;
}
return flag;
}
int main()
{
int w, te;
scanf("%d", &te);
while (te--)
{
cin >> n >> m >> w;
cnt = 0;
init();
for (int s = 0; s < m; s++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);//开始的时候是双向边
add(b, a, c);
}
for (int s = 0; s < w; s++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, -c);//虫洞~~负边
}
// cout << " " << d[3] << endl;
bool ans = spfa();
if (ans)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
while (1)
{
break;
}
// cout << d[n] << endl;
}
return 0;
}