poj1201 Intervals 差分约束

题目大意:

有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。

思路:

设s[i]为从1~i的整数个数。

这样对于区间[ a , b]显然有 S[b+1] - S[a] >=c[i] (为什么是b+1?因为闭区间b也要选上呀)

然后还有

0<= S[B+1]-S[B] <=1 (整数的话最多比前一个大一,好吧,我大二- -|||我不二啊!!)

变形得:

S[B+1]-S[B] >=0

S[B]-S[B+1]>=-1

然后图就可以建立出来啦~~~~

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 #define maxn 50005
 8 int head[maxn];
 9 struct edge{
10     int next,to,w;
11 }e[maxn*3];
12 int n,m,cnt,ans,l=0x7ffff,r;
13 int dis[maxn],cn[maxn];
14 bool vis[maxn];
15 void insert(int u,int v,int k){
16     cnt++;
17     e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=k;
18     head[u]=cnt;
19 }
20 void spfa(){
21     queue<int> q;
22     memset(dis,-1,sizeof dis);
23     for(int i=l;i<=r;i++){
24         vis[i]=1;
25         dis[i]=0;
26         q.push(i);
27     }
28     while(!q.empty()){
29         int now=q.front();
30         vis[now]=0;q.pop();
31         for(int i=head[now];i;i=e[i].next){
32             int s=e[i].to;
33             if(dis[s]<dis[now]+e[i].w)
34             {    
35                 dis[s]=dis[now]+e[i].w;
36                 if(!vis[s]){
37                     vis[s]=1;
38                     q.push(s);
39                 }
40             }
41         }
42     }
43 }
44 int main(){
45     while(~scanf("%d",&n))
46     {
47         int a,b,c;
48         for(int i=1;i<=n;i++){
49         scanf("%d%d%d",&a,&b,&c);
50         insert(a,b+1,c);
51         l=min(l,a);
52         r=max(r,b+1);
53         }
54         for(int i=l;i<=r;i++){
55             insert(i,i+1,0);
56             insert(i+1,i,-1);
57         }
58         spfa();
59         printf("%d",dis[r]);
60     }
61 } 
原文地址:https://www.cnblogs.com/Elfish/p/7647299.html