差分约束的入门题。比2770稍复杂,需要稍微转化一下。 设S[i]是前i个数中选出的个数,则ai到bi的个数即S[bi] - S[ai-1]。因此有S[bi] - S[ai-1] >= ci。另外有S[i] - s[i - 1] >= 0 && S[i] - S[i - 1] <= 1,故建图。 使图中每一组uv,满足 S[ai - 1] <= S[bi] + ci S[i] <= S[i - 1] + 1 S[i - 1] <= S[i] 当不满足时,更新即可。 tips:因为此题必有解(题给出),因此bellmanford只需更新至全部满足即可。 #include <cstdio>#include <string> #define inf 99999 struct Edge{ int u, v, w;} edge[50001]; int n, a[50001], mn, mx; void init(){ int i; for(i = 0; i < 50001; i ++) a[i] = 0; mx = 1, a[0] = 0, mn = inf;} bool bellman_ford(){ int i, t, f = 1; // pa(); // must satisfy following aspects: // s[v] <= s[u] - w // s[i] <= s[i - 1] + 1 // s[i - 1] <= s[i] while(f) { f = 0; for(i = 0; i < n; i ++) { t = a[edge[i].u] + edge[i].w; if(a[edge[i].v] > t) { a[edge[i].v] = t; f = 1; } } for(i = mn; i <= mx; i ++) { t = a[i - 1] + 1; if(a[i] > t) { a[i] = t; f = 1; } } for(i = mx; i >= mn; i --) { t = a[i]; if(a[i - 1] > t) { a[i - 1] = t; f = 1; } } } return true;} int main(){ //freopen("in.txt", "r", stdin); while(scanf("%d", &n) != EOF) { init(); int i, u, v, w; for(i = 0; i < n; i ++) { scanf("%d %d %d", &u, &v, &w); edge[i].u = v, edge[i].v = u - 1, edge[i].w = -w; if(mn > u) mn = u; if(mx < v) mx = v; } bellman_ford(); //pa(); printf("%d\n", a[mx] - a[mn - 1]); } return 0;}

评论