Detecting Anomalies in Currency Exchange Rates

判断有向图是不是存在负环

May 17, 2017

题目链接:pdf

题目给一个有向图,判定这个有向图是不是存在负环。

思路:

对这个图进行Bellman-Ford算法:不断对所有边进行松弛操作,循环进行V次,如果第V次仍然有边被松弛,那么说明存在负环。

相反,如果第V次没有边被松弛,那么说明没有负环。

在讨论Dijkstra算法的时候,最开始的V*E的算法其实就是Bellman-Ford算法。

初始化的时候把dist数组初始化为0。为什么呢?因为我们找的是负环,所以我们可以假设所有点到对源点的距离都是0。如果有负环,那么一定有负边,在第V次松弛所有边的时候,这个环中一定有一个点的最短路为负值。

// Mon May 15 14:13:09 CST 2017
// Mon May 15 15:09:41 CST 2017


// 一个有向图是不是存在负环

#include <iostream>
#include <vector>
#include <utility>

using namespace std;
typedef pair<int, int> PII;	// from, to
struct edge {
  int from;
  int to;
  int w;
};

int negative_cycle(vector<vector<int> > &adj, vector<vector<int> > &cost) {
  vector<int> dist(adj.size(), 0);
  vector<edge> edges;

  for (size_t i = 0; i < adj.size(); ++i) {
    for (size_t j = 0; j < adj[i].size(); ++j) {
      edge e;
      e.from = i;
      e.to = adj[i][j];
      e.w = cost[i][j];
      edges.push_back(e);
    }
  }

  for (size_t i = 0; i < adj.size(); ++i) {
    for (auto &e : edges) {
      int tmp = dist[e.from] + e.w;

      if (dist[e.to] > tmp) {
	dist[e.to] = tmp;
	if (i == adj.size() - 1) {
	  return 1;
	}
      }
    }
  }

  return 0;
}

int main() {
  int n, m;

  cin >> n >> m;
  
  // using this will fail on test19. I don't know why!
  // while(std::cin >> n >> m) {
    vector<vector<int> > adj(n, vector<int>());
    vector<vector<int> > cost(n, vector<int>());
    
    for (int i = 0; i < m; i++) {
      int x, y, w;
      std::cin >> x >> y >> w;
      adj[x - 1].push_back(y - 1);
      cost[x - 1].push_back(w);
    }
    std::cout << negative_cycle(adj, cost) << "\n";
  // }

  return 0;
}

comments powered by Disqus