题意:
给定一个数轴上的 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 }