差分约束--P1645 序列(论如何一份代码水了三道蓝题)
*三道题的链接 P1645 序列 P1986 元旦晚会 SP116 INTERVAL - Intervals 除了第三题是多组样例,其他的都一模一样
*差分约束的条件:给定$n$个变量和$m$个不等式,每个不等式形如$x_i-x_j\le s_k$,求$x_{n}-x_1$的最大值,例如:
\begin{cases}x_1-x_0\le 2\\x_2-x_0\le 7\\x_3-x_0\le 8\\x_2-x_1\le 3\\x_3-x_2\le 2\end{cases}
这里差分约束就不具体说明了,以前好像写过但是好像被我删掉惹(⊙v⊙)另外在建图过程中如果求的是两个变量差的最大值,那么将所有不等式转化为<=的形式,并求最短路;如果求两个变量差的最小值,那么将所有不等式转化为>=的形式,并求最长路。
*那么对于这道题有几个显然的式子:
\begin{cases} x_k-x_{k+1}\ge 0\\x_{k+1}-x_k\ge -1\\x_r-x_{l-1}\ge c\end{cases}
其中第一个式子表示,单位长度为1的区间内数字个数非负,第二个式子表示单位长度为1的区间内数字个数不超过1,最后一个式子表示$l-r$的区间内的数字个数不小于$c$
完整代码:
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 #include <queue>
6 #define int long long
7 using namespace std;
8 int n,ll=1e9+7,rr=-1;
9 const int maxn=1e5+10;
10 struct node{
11 int to,next,w;
12 }ed[2*maxn];
13 int dis[maxn],head[maxn],tot,m,vis[maxn];
14 void add(int u,int to,int w){
15 ed[++tot].w=w;
16 ed[tot].to=to;
17 ed[tot].next=head[u];
18 head[u]=tot;
19 }
20 int SPFA(int s){
21 queue<int> q;
22 for (int i = ll;i <= rr;i++) dis[i]=-1e9+7; dis[s]=0;
23 memset(vis,0,sizeof(vis)); vis[s]=1;
24 q.push(s);
25 while (!q.empty()){
26 int x=q.front();q.pop();
27 vis[x]=0;
28 for (int i = head[x];i;i=ed[i].next){
29 int to=ed[i].to;
30 if(dis[to]<dis[x]+ed[i].w){
31 dis[to]=dis[x]+ed[i].w;
32 if (!vis[to]){
33 vis[to]=1;
34 q.push(to);
35 }
36 }
37 }
38 }
39 return dis[rr];
40 }
41 signed main(){
42 scanf ("%lld%lld",&n,&m);
43 for (int i = 1;i <= m;i++){
44 int l,r,c;
45 scanf ("%lld%lld%lld",&l,&r,&c);
46 add(l-1,r,c);
47 ll=min(ll,l-1);rr=max(rr,r);
48 }
49 for (int i = ll;i < rr;i++) add(i,i+1,0),add(i+1,i,-1);
50 int ans=SPFA(ll);
51 printf("%lld\n",ans);
52 return 0;
53 }