差分约束的版。第一次接触这个算法。这里记录一下
理解代码就看这里吧 http://www.cnblogs.com/scau20110726/archive/2012/11/29/2795153.html 感觉写的挺易懂的。跟下面的代码也出入不大
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} #define MAXN 210 int N,M,cnt; int head[MAXN]; struct node { int v,w; int next; }edge[MAXN * 4]; bool used[MAXN]; int dis[MAXN],num[MAXN]; bool inq[MAXN]; void read() { cnt = 0; memset(head,-1,sizeof(head)); memset(used,false,sizeof(used)); scanf("%d",&M); while (M--) { char op[10]; int u,v,k; scanf("%d%d%s%d",&u,&v,op,&k); v += u; u --; used[u] = used[v] = true; if (strcmp(op,"gt") == 0) { k++; edge[cnt].v = u; edge[cnt].w = -1 * k; edge[cnt].next = head[v]; head[v] = cnt++; } else { k--; edge[cnt].v = v; edge[cnt].w = k; edge[cnt].next = head[u]; head[u] = cnt++; } } used[N + 1] = true; for (int i = 0; i <= N; i++) { if (!used[i]) continue; edge[cnt].v = i; edge[cnt].w = 0; edge[cnt].next = head[N + 1]; head[N + 1] = cnt ++; } } bool SPFA() { memset(dis,0x3f,sizeof(dis)); memset(inq,false,sizeof(inq)); memset(num,0,sizeof(num)); queue<int>q; while (!q.empty()) q.pop(); q.push(N + 1); dis[N + 1] = 0; num[N + 1] = 1; while (!q.empty()) { int u = q.front();q.pop(); inq[u] = false; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v , w = edge[i].w; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if (!inq[v]) { inq[v] = true; q.push(v); num[v] ++; if (num[v] > N + 1) return true; } } } } return false; } int main() { while (scanf("%d",&N) != EOF) { if (N == 0) break; read(); if (SPFA()) puts("successful conspiracy"); else puts("lamentable kingdom"); } return 0; }
另外贴出SPFA的DFS判负环代码记录一下
int spfa_dfs(int u) { vis[u]=1; for(int k=first[u]; k!=-1; k=e[k].next) //遍历顶点u的邻接表 { int v=e[k].v , w=e[k].w; if( d[u]+w < d[v]) { d[v]=d[u]+w; if(!vis[v]) { if(spfa_dfs(v)) return 1; } else return 1; } } vis[u]=0; return 0; }