原题链接:http://poj.org/problem?id=3259
题意
有个很厉害的农民,它可以穿越虫洞去他的农场,当然他也可以通过道路,虫洞都是单向的,道路都是双向的,道路会花时间,虫洞会倒退时间,问你这个农民可不可以回到起点,并且在他出发的时间之前。
题解
就虫洞用负边链接,然后判断是否有负环即可。
代码
#include<iostream> #include<cstring> #include<vector> #include<string> #include<algorithm> #include<queue> #define INF 2500003 #define MAX_N 555 using namespace std; struct edge { public: int to, cost; edge(int t, int c) : to(t), cost(c) { } edge() { } }; vector<edge> G[MAX_N]; int d[MAX_N]; queue<int> que; bool inQue[MAX_N]; bool vis[MAX_N]; int n,m,w; int cnt[MAX_N]; void init(){ for(int i=0;i<=n;i++)G[i].clear(); fill(d,d+n+1,INF); memset(vis,0,sizeof(vis)); while(que.size())que.pop(); memset(inQue,0,sizeof(inQue)); memset(cnt,0,sizeof(cnt)); } bool spfa(int s) { que.push(s); inQue[s] = 1; vis[s] = 1; d[s] = 0; cnt[s] = 1; while (que.size()) { int u = que.front(); que.pop(); inQue[u] = 0; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; int c = G[u][i].cost; if (d[u] + c < d[v]) { d[v] = d[u] + c; if (!inQue[v]) { inQue[v] = 1; que.push(v); cnt[v]++; if (cnt[v] > n)return true; } } } } return false; } int T; int main() { cin.sync_with_stdio(false); cin >> T; while (T--) { cin >> n >> m >> w; init(); for (int i = 0; i < m; i++) { int u, v, c; cin >> u >> v >> c; G[u].push_back(edge(v, c)); G[v].push_back(edge(u, c)); } for (int i = 0; i < w; i++) { int u, v, c; cin >> u >> v >> c; G[u].push_back(edge(v, -c)); } bool flag = false; for (int i = 0; i < n; i++) if (!vis[i]) { flag = spfa(i); if (flag) break; } if (flag)cout << "YES" << endl; else cout << "NO" << endl; } return 0; }