loj10087
Southwestern Europe 2002,题面可参考 POJ 1201。
给定 n 个闭区间 [a_i,b_i] 和 n 个整数c_i 。你需要构造一个整数集合Z ,使得对于任意i (1<=i<=n),Z 中满足 a_i<=x<=b_i 的整数 x 不少于 c_i 个,求这样的整数集合 Z 最少包含多少个数。
简而言之就是,从 0~5E4 中选出尽量少的整数,使每个区间 [a_i,b_i] 内都有至少 c_i 个数被选出。
输入格式
第一行一个整数 n,表示区间个数;
以下 n 行每行描述这些区间,第 i+1 行三个整数 a_i,b_i,c_i,由空格隔开。
输出格式
一行,输出满足要求的序列最少整数个数。
样例
数据范围与提示
对于全部数据,1<=n<=5e4,0<=a_i,b_i<=5e4。
______________________________________
区间型差分约束
________________________________________
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=5e4+10; 4 struct edge 5 { 6 int u,v,w,nxt; 7 }e[maxn<<2]; 8 int head[maxn],js; 9 void addage(int u,int v,int w) 10 { 11 e[++js].u=u,e[js].v=v;e[js].w=w; 12 e[js].nxt=head[u];head[u]=js; 13 } 14 int n; 15 int dis[maxn]; 16 bool inq[maxn]; 17 deque<int>q; 18 19 int spfa(int u) 20 { 21 q.push_back(u); 22 memset(dis,0xff,sizeof dis); 23 inq[u]=1; 24 dis[u]=0; 25 while(!q.empty()) 26 { 27 int u=q.front();q.pop_front(); 28 inq[u]=0; 29 for(int i=head[u];i;i=e[i].nxt) 30 { 31 int w=e[i].w,v=e[i].v; 32 if(dis[u]+w>dis[v]) 33 { 34 dis[v]=dis[u]+w; 35 if(!inq[v]) 36 { 37 if(!q.empty() && dis[q.front()]<dis[v])q.push_front(v); 38 else q.push_back(v); 39 inq[v]=1; 40 } 41 } 42 } 43 } 44 return dis[50001]; 45 } 46 int main() 47 { 48 scanf("%d",&n); 49 for(int a,b,c,i=0;i<n;++i) 50 { 51 scanf("%d%d%d",&a,&b,&c); 52 addage(a,b+1,c); 53 } 54 for(int i=1;i<=50001;++i) 55 { 56 addage(i-1,i,0); 57 addage(i,i-1,-1); 58 } 59 cout<<spfa(0); 60 61 return 0; 62 }