一.原题链接:http://poj.org/problem?id=3259
二.题目大意:从一个田地开始可以花Ts到另一田地,并且回来是同一时间。(双向边)田地之间有虫洞,单向边,走过虫洞可以使时间倒流。问能不能从某一个田地出发,回到改田地使得时光倒流。
三.思路:就是判断有没有负环,有的话就YES,否则NO。
四.AC代码:
spfa:
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int MAX_SIZE = 520, INF = 1<<29, MOD = 1000000007; int graph[MAX_SIZE][MAX_SIZE]; //PedgeNum 表示正边数,NedgeNum表示负边数 int nodeNum, PedgeNum, NedgeNum; void initGraph() { int i, j; for(i = 0; i < MAX_SIZE; i++) for(j = 0; j < MAX_SIZE; j++) graph[i][j] = INF; } //有负环返回 false, 否则返回 true bool spfa() { int dist[MAX_SIZE], cnt[MAX_SIZE] = {0}, i, j, cur; bool inQue[MAX_SIZE] = {0}; queue <int> que; //设0为起点 for(i = 1; i <= nodeNum; i++) dist[i] = (1 == i? 0:INF); que.push(1); inQue[1] = true; cnt[1]++; while(!que.empty()){ cur = que.front(); inQue[cur] = false; que.pop(); for(i = 1; i <= nodeNum; i++){ if(dist[i] > dist[cur] + graph[cur][i]){ dist[i] = dist[cur] + graph[cur][i]; if(cnt[i] > nodeNum-1) return false; if(!inQue[i]){ que.push(i); inQue[i] = true; cnt[i]++; } } } } return true; } int main() { //freopen("in.txt", "r", stdin); int test, i, j, S, E, weight; cin>>test; while(test--){ cin>>nodeNum>>PedgeNum>>NedgeNum; initGraph(); for(i = 0; i < PedgeNum; i++){ cin>>S>>E>>weight; if(graph[S][E] > weight){ graph[S][E] = weight; graph[E][S] = weight; } } for(i = 0; i < NedgeNum; i++){ cin>>S>>E>>weight; graph[S][E] = -weight; } if(spfa()) cout<<"NO\n"; else cout<<"YES\n"; } }
bellman_Ford:
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int MAX_SIZE = 520, INF = 1<<29, MOD = 1000000007; //PedgeNum 表示正边数,NedgeNum表示负边数 int nodeNum, PedgeNum, NedgeNum, edgeNum; struct Edge { int S, E, weight; }; Edge edge[MAX_SIZE*MAX_SIZE]; //有负环返回 false, 否则返回 true bool bellman_Ford() { int dist[MAX_SIZE], i, j, flag; for(i = 1; i <= nodeNum; i++) dist[i] = (1 == i? 0:INF); for(i = 1; i < nodeNum; i++){ flag = false; for(j = 0; j < edgeNum; j++) if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight){ dist[edge[j].E] = dist[edge[j].S] + edge[j].weight; flag = true; } if(!flag) return true; //正常情况下这里只是 break 但是这里只要判断负环,可直接返回 } for(j = 0; j < edgeNum; j++) if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight) return false; return true; } int main() { //freopen("in.txt", "r", stdin); int test, i, j, S, E, weight; cin>>test; while(test--){ cin>>nodeNum>>PedgeNum>>NedgeNum; edgeNum = 0; for(i = 0; i < PedgeNum; i++){ cin>>S>>E>>weight; edge[edgeNum].S = edge[edgeNum + 1].E = S; edge[edgeNum].E = edge[edgeNum + 1].S = E; edge[edgeNum].weight = edge[edgeNum + 1].weight = weight; edgeNum += 2; } for(i = 0; i < NedgeNum; i++){ cin>>S>>E>>weight; edge[edgeNum].S = S; edge[edgeNum].E = E; edge[edgeNum].weight = - weight; edgeNum++; } if(bellman_Ford()) cout<<"NO\n"; else cout<<"YES\n"; } }