|
思路:
差分约束是个很神奇的东西,能将下面这种类型的不等式约束问题: d[1] - d[2] <= a d[4] - d[7] <= b ... 求 d[x] 的最大/小值 转化为最短路径的问题,真吗的太牛逼了。 原理呢,就是一个图求出单源最短路径之后。 两点之间的关系必然是满足 d[u] + w[u,v] >= d[v] 的,没法再松弛了。
对于这道题,有两种约束: 1. 输入里指明的约束 2. d[1] <= d[2] <= d[3] .... <= d[N] 建立完这两种约束之后,然后spfa求一下最短路径。 如果有负环,就输出 -1 如果不连通,就输出 -2
#include <stdio.h>
#define MAX_DIS 1000000032 #define MAX_N 1024 #define MAX_EDGES 65536
struct edge_node { int i, w; struct edge_node *next; };
int N, ML, MD; struct edge_node edges[MAX_EDGES], *map[MAX_N]; int edges_cnt; int D[MAX_N], queue[MAX_N], head, tail, vis[MAX_N], tm, cnt[MAX_N];
inline void add_edge(int a, int b, int w) { struct edge_node *e = &edges[edges_cnt++];
e->i = b; e->w = w; e->next = map[a]; map[a] = e; }
inline int push(int i, int d) { if (d >= D[i]) return 0; D[i] = d; if (vis[i] == tm) return 0; vis[i] = tm; cnt[i]++; if (cnt[i] >= N) return 1; queue[tail++] = i; tail &= MAX_N - 1; return 0; }
inline int spfa() { int i; struct edge_node *e;
for (i = 1; i <= N; i++) D[i] = MAX_DIS; tm++; head = tail = 0; push(1, 0); while (head != tail) { i = queue[head++]; head &= MAX_N - 1; vis[i] = 0; for (e = map[i]; e; e = e->next) if (push(e->i, D[i] + e->w)) return 1; }
return 0; }
int main() { int a, b, w, i;
freopen("e:\\test\\in.txt", "r", stdin);
scanf("%d%d%d", &N, &ML, &MD); while (ML--) { scanf("%d%d%d", &a, &b, &w); add_edge(a, b, w); } while (MD--) { scanf("%d%d%d", &a, &b, &w); add_edge(b, a, -w); } for (i = 2; i <= N; i++) add_edge(i, i - 1, 0);
if (spfa()) a = -1; else a = (D[N] == MAX_DIS) ? -2 : D[N]; printf("%d\n", a);
return 0; }
|