题目描述:
Farmer John 在探索农场的时候 惊奇的发现一些虫洞,虫洞是一个特殊的东西,他是一个单向通道,他能到达虫洞的另一端, 可以穿越到达之前的时间。Farmer John 的由N个农场组成, 编号是 1-N, M条单向通道, W个虫洞。
Farmer John 是个时空穿越迷, 他想要做到一下几点: 开始在一些农场,旅行通过虫洞或者是路,通过虫洞能返回到他之前的时间。
帮助Farmer John 他是否有可能穿越到之前的时间, 他将会给你完整的地图, 他有F个农场, 走过这段路径的长度是小于10000秒的, 并且虫洞的穿越也是不会超过10000秒的
输入:
F代表测试实例的个数
第二行三个整数 N, M ,W 分别用空格隔开
接下来M行 是M个道路 ,道路是双向的。 S, E ,T 代表从S到E话费时间为T。
接下来W行 代表W个虫洞, 虫洞是单向, S, E, T,代表 从S 到 E 穿越的时间是 T。
题目分析:
他问你是否能穿越,其实就是问有无负权环。 直接SPFA 判断
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <cstring> using namespace std; #define INF 0xfffffff #define maxn 520 struct Edge { int e, w; Edge(int e=0,int w=0) : e(e), w(w) {} }; bool vis[maxn]; int use[maxn], dist[maxn]; int n, m, w; vector<Edge> G[maxn]; void Init() { memset(vis,false,sizeof(vis)); for(int i=0; i<=n; i++) dist[i] = INF, use[i] = 0; } bool Spfa(int Star) { Edge P, Pn; queue<Edge> Q; P.e = Star, P.w = 0; Q.push(P); use[Star] = 1; dist[Star] = 0; while( !Q.empty() ) { P = Q.front(); Q.pop(); vis[P.e] = false; int len = G[P.e].size(); for(int i=0; i<len; i++) { Pn = G[P.e][i]; if( dist[Pn.e] > dist[P.e] + Pn.w ) { dist[Pn.e] = dist[P.e] + Pn.w; if( !vis[Pn.e] ) { vis[Pn.e] = true; Q.push(Pn); use[Pn.e] ++; if(use[Pn.e] >= n && dist[Pn.e] < 0) return true; } } } } return false; } bool Slove() { for(int i=1; i<=n; i++) { Init(); if( Spfa(i) ) return true; } return false; } int main() { int T; cin >> T; while(T--) { cin >> n >> m >> w; int a, b, c; for(int i=0; i<=n; i++) G[i].clear(); for(int i=0; i<m; i++) { scanf("%d%d%d",&a,&b,&c); G[a].push_back( Edge(b,c) ); G[b].push_back( Edge(a,c) ); } for(int i=0; i<w; i++) { scanf("%d%d%d",&a,&b,&c); G[a].push_back( Edge(b,-c) ); } if( Spfa(i) ) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }