能否无限穿越到从前,就是问是否存在一个负环。这里可以用Bellman_ford算法来判断。
Bellman_ford算法模板:
前面先遍历n-1是代表最坏的情况是遍历n-1,求出最优的解,继续第n次操作,最优解应当和第n-1次操作相同,如果不同,那么就是存在负环。
bool bellman_ford(int s) { for(int i = 0; i < n; i++) { d[i] = INF; } d[s] = 0; int x ,y; for(int k = 0; k < n-1; k++) { //迭代n-1次 for(int i = 0; i < m; i++) { //检查每条边 x = u[i], y = v[i]; if(d[x] < INF) { d[y] = min(d[y], d[x] + w[i]); } } } for(int i = 0; i < m; i++) { x = u[i] , y = v[i]; int tmp = d[y]; d[y] = min(d[y], d[x] + w[i]); if(d[y] != tmp) { return false; } } return true; }
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 2005; const int INF = 0x3f3f3f3f; int u[maxn],v[maxn],w[maxn]; int d[maxn]; int n,m; bool bellman_ford(int s) { for(int i = 0; i < n; i++) { d[i] = INF; } d[s] = 0; int x ,y; for(int k = 0; k < n-1; k++) { //迭代n-1次 for(int i = 0; i < m; i++) { //检查每条边 x = u[i], y = v[i]; if(d[x] < INF) { d[y] = min(d[y], d[x] + w[i]); } } } for(int i = 0; i < m; i++) { x = u[i] , y = v[i]; int tmp = d[y]; d[y] = min(d[y], d[x] + w[i]); if(d[y] != tmp) { return false; } } return true; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i = 0; i < m; i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); } int ok = bellman_ford(0); if(ok) { printf("not possible\n"); }else { printf("possible\n"); } } return 0; }
用邻接表的方法:
#include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 1005; struct Edge { int from ,to ,dist; Edge(int u,int v,int d) { from = u; to = v; dist = d; } }; struct Bellman { int n,m; vector<Edge> edges; vector<int> G[maxn]; bool done[maxn]; int d[maxn]; int p[maxn]; int inq[maxn],cnt[maxn]; void init(int n) { this->n = n; for(int i = 0; i < n; i++) { G[i].clear(); } edges.clear(); } void addEdge(int from,int to,int dist) { edges.push_back(Edge(from, to, dist)); m = edges.size(); G[from].push_back(m-1); } bool bellman_ford(int s) { queue<int> Q; memset(inq,0,sizeof(inq)); memset(cnt,0,sizeof(cnt)); for(int i = 0; i < n; i++) { d[i] = INF; } d[s] = 0; inq[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = false; for(int i = 0; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; if(d[u] < INF && d[e.to] > d[u] + e.dist) { d[e.to] = d[u] + e.dist; p[e.to] = G[u][i]; if(!inq[e.to]) { Q.push(e.to); inq[e.to] = true; if(++cnt[e.to] > n) { return false; } } } } } return true; } }; int main() { Bellman bell; int T; int n,m; int u,v,dist; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); bell.init(n); for(int i = 0; i < m; i++) { scanf("%d%d%d",&u,&v,&dist); bell.addEdge(u,v,dist); } int ok = bell.bellman_ford(0); if(!ok) { printf("possible\n"); }else { printf("not possible\n"); } } return 0; }