差分约束--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 }

 

posted @ 2020-10-12 14:56  小又又  阅读(247)  评论(0编辑  收藏  举报