博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷 P1645】 序列 (差分约束)
阅读量:6842 次
发布时间:2019-06-26

本文共 1537 字,大约阅读时间需要 5 分钟。

差分约束。
\(s[i]\)表示前\(i\)个位置有多少个数,那么对于一个限制条件\((L,R,C)\),显然有
\[s[R]-s[L-1]>=C\]
于是连一条\(L-1\)\(R\)边权为\(C\)的边。
但为了保证能从\(0\)走到\(max(b)\),我们还需从\(1\)\(n\),对\(i-1\)\(i\)连一条权为\(0\)的边,对\(i\)\(i-1\)连一条权为\(-1\)的边,
这也很好理解,因为
\[s[i]-s[i-1]>=0,s[i-1]-s[i]>=-1\]
显然成立。
然后从\(0\)\(max(b)\)跑一遍最长路就好了。注意有正权边,所以不能跑Dijkstra,跑SPFA。

#include 
#include
#include
#include
using namespace std;#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);#define Close fclose(stdin);fclose(stdout);const int MAXN = 1010;int n, a, b, c, r;struct Edge{ int next, to, dis;}e[MAXN << 2];int head[MAXN], num;inline void Add(int from, int to, int dis){ e[++num] = (Edge){ head[from], to, dis }; head[from] = num;}queue
q;int dis[MAXN], vis[MAXN];int main(){ Open("sequence"); scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d%d%d", &a, &b, &c); r = max(r, b); Add(a - 1, b, c); } for(int i = 1; i <= r; ++i) Add(i - 1, i, 0), Add(i, i - 1, -1); memset(dis, 128, sizeof dis); dis[0] = 0; q.push(0); while(!q.empty()){ int now = q.front(); q.pop(); vis[now] = 0; for(int i = head[now]; i; i = e[i].next) if(dis[e[i].to] < dis[now] + e[i].dis){ dis[e[i].to] = dis[now] + e[i].dis; if(!vis[e[i].to]) q.push(e[i].to), vis[e[i].to] = 1; } } printf("%d\n", dis[r]); Close; return 0;}

转载于:https://www.cnblogs.com/Qihoo360/p/9685441.html

你可能感兴趣的文章