POJ 3259 Wormholes(最短路,判断有没有负环回路)

Hint

For farm 1, FJ cannot travel back in time. 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.

这题就是判断存不存在负环回路。

前M条是双向边,,后面的W是单向的负边。

为了防止出现不连通,

增加一个结点作为起点。

起点到所有点的长度为0bellman_ford算法模板,可以处理图是否存在负环现象;/* * POJ 3259 * 判断图中是否存在负环回路。 * 为了防止图不连通的情况,增加一个点作为起点,这个点和其余的点都相连,且距离为0。 */#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-9using namespace std;/* * 单源最短路bellman_ford算法,复杂度O(VE) * 可以处理负边权图。 * 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路 * vector<Edge>G;先G.clear()初始化,然后加入所有边 * 假设图不存在负环,那么最短路最多经过(起点不算)n-1个结点,可以通过"n-1"轮松弛操作得到最短路; * 点的编号从1开始(从0开始简单修改就可以了) */ typedef long long ll;typedef pair<int,int>P;const int M = 600;const int INF = 0x3f3f3f3f;const int mod = 10000007;int d[M];struct Edge {int u,v,c;Edge(int _u = 0,int _v = 0,int _c = 0):u(_u),v(_v),c(_c) {}};vector<Edge>G;bool bellman_ford(int start,int n) { //点的编号从1开始for(int i = 1; i <= n; i++) d[i] = INF;d[start] = 0;for(int i = 1; i < n; i++) { //最多松弛n-1次bool flag = true;for(int j = 0; j < G.size(); j++) {if(d[G[j].v] > d[G[j].u] + G[j].c) {flag = false;d[G[j].v] = d[G[j].u] + G[j].c;}}if(flag) return true; //没有负环回路}for(int i = 0; i < G.size(); i++) {if(d[G[i].v] > d[G[i].u] + G[i].c) return false; //有负环回路}return true; //没有负环回路}int main() {int T,n,m,w;cin>>T;while(T–) {G.clear();scanf("%d %d %d",&n,&m,&w);for(int i = 0; i < m; i++) {int u,v,c;scanf("%d %d %d",&u,&v,&c);G.push_back(Edge(u,v,c));G.push_back(Edge(v,u,c));}for(int i = 0; i < w; i++) {int u,v,c;scanf("%d %d %d",&u,&v,&c);G.push_back(Edge(u,v,-c));}for(int i = 1; i <= n; i++) {G.push_back(Edge(n + 1,i,0));}if(bellman_ford(n + 1,n + 1)) puts("NO");else puts("YES");}return 0;}

自然而然不想去因为别人的努力而努力,

POJ 3259 Wormholes(最短路,判断有没有负环回路)

相关文章:

你感兴趣的文章:

标签云: