【差分约束】POJ1201/LG SP116 Intervals

题意翻译

区间取数

题目描述

有n个区间,在区间[ai,bi]中至少取任意互不相同的ci个整数。求在满足n个区间的情况下,至少要取多少个正整数。

输入输出格式

输入格式

多组数据。

第一行的一个整数T表示数据个数。对于每组数据,第一行包含一个整数nn(11<=nn<=5000050000)表示区间数。以下nn行描述区间。输入的第(i+1)行包含三个整数ai,bi,ci,由空格分开。其中0<=ai<=bi<=500001<=ci<=bi-ai+1。

输出格式

对于每组数据,输出一个对于n个区间[ai,bi] 至少取ci个不同整数的数的总个数。

输入输出样例

输入样例#11
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
输出样例#16
T

这道题呢又是一个差分约束

很明显通过题意可以抽象出很多个b-(a-1)>=c

而且还有一点隐藏的东西1>=i-(i-1)>=0

转换一下下就是i-(i-1)>=0,i-(i-1)>=-1

因为是大于,所以差分的时候要跑最长路

再次记忆一下,b-a>=a,建a到b的单向边

然后堆栈spfa就能A了

代码

 1 #include<cstdio>
 2 #include<queue>
 3 #include<cstring>
 4 #define N 50011
 5 using namespace std;
 6 struct star{int to,nxt,val;}edge[10*N];
 7 int dis[N],head[N],stk[N],mi=0x7f7f7f7f,ma=-1;
 8 int cnt=1,n,a,b,c,top,t;
 9 bool in[N];
10 inline void add(int u,int v,int w)
11 {
12     edge[cnt].nxt=head[u];
13     edge[cnt].to=v;
14     edge[cnt].val=w;
15     head[u]=cnt++;
16 }
17 int main()
18 {
19     scanf("%d",&t);
20     while(t--)
21     {
22         memset(head,-1,sizeof(head));
23         memset(dis,~0x7f,sizeof(dis));
24         cnt=1;
25         scanf("%d",&n);
26         for(int i=1;i<=n;i++)
27         {
28             scanf("%d%d%d",&a,&b,&c);
29             add(a-1,b,c);
30             mi=min(a-1,mi);
31             ma=max(ma,b);
32         }
33         for(int i=mi;i<=ma;i++)
34             add(i,i-1,-1),add(i-1,i,0);
35         stk[++top]=mi;
36         dis[mi]=0,in[mi]=1;
37         while(top)
38         {
39             int now=stk[top--];in[now]=0;
40             for(int i=head[now];i!=-1;i=edge[i].nxt)
41             {
42                 int to=edge[i].to;
43                 if(dis[to]<dis[now]+edge[i].val)
44                 {
45                     dis[to]=dis[now]+edge[i].val;
46                     if(!in[to])
47                     {stk[++top]=to;in[to]=1;}
48                 }
49             }
50         }
51         printf("%d
",dis[ma]);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10162372.html