还是那句话:差分约束条件题目的难点是“怎么找到问题的约束条件”。
这题输入的边有两种格式:
1. 边长确定,即xi - xj = b; 可以转化成 xi - xj <= b 和 xi - xj >=b (即 xj - xi <= -b).
2. 边长不定,xi - xj >= 1; 可以转化成 xj - xi <= -1;
下面用SPFA算法实现:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXV 1005 #define MAXE 201005 #define INF 100000000 struct { int e, v; } edge[MAXE]; int n, neg; int dis[MAXV], cnt[MAXV]; int node[MAXV], next[MAXE]; int Q[MAXV], vst[MAXV]; void add(int s, int e, int v) { edge[neg].e = e; edge[neg].v = v; next[neg] = node[s]; node[s] = neg++; } int relax(int s, int e, int v) { if (dis[s]+v < dis[e]) { dis[e] = dis[s]+v; return 1; } return 0; } // 栈实现的。 int SPFA(int s0) { int i, t, p, top; memset(cnt, 0, sizeof(cnt)); memset(vst, 0, sizeof(vst)); for (i=0; i<=n; i++) dis[i] = INF; dis[s0] = 0; Q[0] = s0; top = 1; vst[s0] = 1; cnt[s0]++; while (top) { t = Q[--top]; vst[t] = 0; p = node[t]; while (p != -1) { if (relax(t, edge[p].e, edge[p].v) && !vst[edge[p].e]) { Q[top++] = edge[p].e; vst[edge[p].e] = 1; cnt[edge[p].e]++; if (cnt[edge[p].e] > n+1) return 0; } p = next[p]; } } return 1; } int main() { int m, a, b, c, i; char f; while (scanf("%d %d", &n, &m) != EOF) { neg = 0; memset(node, -1, sizeof(node)); while (m--) { scanf("%*c %c %d %d", &f, &a, &b); if (f == 'P') { scanf("%d", &c); add(a, b, c); add(b, a, -c); } else add(b, a, -1); } //添加一个结点0作为源点 for (i=1; i<=n; i++) add(0, i, 1); if (SPFA(0)) printf("Reliable/n"); else printf("Unreliable/n"); } }