题意:
给定一个数轴上的 n 个区间,要求在数轴上选取最少的点使得第 i 个区间 [ai, bi] 里至少有 ci 个点
使用差分约束系统的解法解决这道题Input
输入第一行一个整数 n 表示区间的个数,接下来的 n 行,每一行两个用空格隔开的整数 a,b 表示区间的左右端点。1 <= n <= 50000, 0 <= ai <= bi <= 50000 并且 1 <= ci <= bi - ai+1。
Output
输出一个整数表示最少选取的点的个数
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
My Solution :
差分约束思想:
关键在于构造不等式组(包括解的合理性)==> 单源最短路
对于差分约束中的每一个不等式约束 xi - xj <= c, 都可以移项变形为xi <=xj +c
与图的最短路问题中的松弛操作类似 (dis [ i ] <= dis [ j ] + w( i , j )
具体做法:
记 dis [ i ]表示数轴上 [ 0,i ]之间选点的个数
对于第i个区间 [ai,bi] 需要满足 dis [bi] - dis [ai-1]>=ci,
注意:为保证dis有意义:需满足0<= dis [ i ] - dis [ i-1 ] <= 1
Code:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<queue>
6 using namespace std;
7
8 int maxn,tot;
9 int head[50010],dis[50010];
10 queue<int>q;
11
12 struct node{
13 int v,x;
14 int next;
15 }e[50010*3];
16
17 bool b[50010];
18
19 void add(int u,int v,int w)
20 {
21 e[++tot].v=v;
22 e[tot].x=w;
23 e[tot].next=head[u];
24 head[u]=tot;
25 }
26 void spfa()
27 {
28 memset(dis,-1,sizeof dis);
29 q.push(0);
30 dis[0]=0;
31
32 while(!q.empty())
33 {
34 int u=q.front();q.pop();b[u]=0;
35 for(int i=head[u];i;i=e[i].next)
36 {
37 int v=e[i].v;
38 if(dis[v]<dis[u]+e[i].x) //松弛操作
39 {
40 dis[v]=dis[u]+e[i].x;
41 if(!b[v])
42 b[v]=1,q.push(v);
43 }
44 }
45 }
46 return ;
47 }
48 int main()
49 {
50 int n,a,b,c;
51 scanf("%d",&n);
52 for(int i=0;i<n;i++)
53 {
54 scanf("%d%d%d",&a,&b,&c);
55
56 add(a,++b,c);
57 maxn=std::max(maxn,b);
58 }
59 for(int i=1;i<=maxn;i++)
60 {
61 add(i-1,i,0);
62 add(i,i-1,-1);
63 }
64 spfa();
65 printf("%d",dis[maxn]);
66
67 return 0;
68 }