【spfa】——poj1874——模板*2
Wormholes
Time Limit: 2000MS |
|
Memory Limit: 65536K |
Total Submissions: 44709 |
|
Accepted: 16453 |
Description
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.
Input
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.
Output
Sample Input
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 8
Sample Output
NO YES
Hint
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 <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; int F,N,M,W; const int INF = 1 << 30; struct Edge { int e,w; Edge(int ee,int ww):e(ee),w(ww) { } Edge() { } }; vector<Edge> G[1000]; //整个有向图 int updateTimes[1000]; //最短路的改进次数 int dist[1000]; //dist[i]是源到i的目前最短路长度 int Spfa(int v) { for( int i = 1; i <= N; ++i) dist[i] = INF; dist[v] = 0; queue<int> que; que.push(v); memset(updateTimes ,0,sizeof(updateTimes)); while( !que.empty()) { int s = que.front(); que.pop(); for( int i = 0;i < G[s].size(); ++i) { int e = G[s][i].e; if( dist[e] > dist[s] + G[s][i].w ) { dist[e] = dist[s] + G[s][i].w; que.push(e); //没判队列里是否已经有e,可能会慢一些 ++updateTimes[e]; if( updateTimes[e] >= N)//某一条边可找到大于 n 次的更小路径值 return true; } } } return false; } int main() { cin >> F; while( F--) { cin >> N >> M >> W; for( int i = 1; i <1000; ++i) G[i].clear(); int s,e,t; for( int i = 0; i < M; ++ i) { cin >> s >> e >> t; G[s].push_back(Edge(e,t)); G[e].push_back(Edge(s,t)); } for( int i = 0;i < W; ++i) { cin >> s >> e >> t; G[s].push_back(Edge(e,-t));//虫洞看做负权边 } if( Spfa(1)) cout << "YES" <<endl; else cout << "NO" <<endl; } }
#include<iostream> #include<string.h> #include<vector> #include<queue> using namespace std; vector<pair<int,int> >g[3000]; queue<int>que; int n,m,src,w; int dist[3000]; bool inQue[3000]; int uptime[3000]; int flag; void spfa() { memset(dist,0x3f3f3f3f,sizeof(dist)); memset(uptime,0,sizeof(uptime)); memset(inQue,false,sizeof(inQue)); dist[src]=0; while(!que.empty())que.pop(); que.push(src); inQue[src]=true; while(!que.empty()) { int u=que.front(); que.pop(); for(int i=0;i<g[u].size();i++) { if(dist[u]+g[u][i].second<dist[g[u][i].first]) { dist[g[u][i].first]=dist[u]+g[u][i].second; if(!inQue[g[u][i].first]) { inQue[g[u][i].first]=true; que.push(g[u][i].first); ++uptime[g[u][i].first]; if(uptime[g[u][i].first]>=n) { flag=1; return ; } } } } inQue[u]=false; } } int main() { int t; cin>>t; while(t--) { cin>>n>>m>>w; flag=0; for(int i=1;i<3000;i++) g[i].clear(); int s,e,t; for(int i=0;i<m;i++) { cin>>s>>e>>t; g[s].push_back(make_pair(e,t)); g[e].push_back(make_pair(s,t)); } for(int i=0;i<w;i++) { cin>>s>>e>>t; g[s].push_back(make_pair(e,-t)); } src=1; spfa(); if(flag==1) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }