【SPOJ116】Intervals

题目大意:有 N 个区间,在区间 [a, b] 中至少取任意互不相同的 c 个整数。求在满足 N 个区间约束的情况下,至少要取多少个正整数。

题解:差分约束系统模板题。
差分约束系统是对于 N 个变量的 M 组线性约束,每组约束满足的条件形如 \(X_i\le X_j+c\)。当所有约束条件均得到满足的时候,意味着以上 M 组不等式均成立。这时,类比于图论中的单源最短路模型,即:当对一个有向图求完单源最短路算法之后,对于图中每一个节点均满足 \(d[i]\le d[j]+e(i,j)\)。因此,可以将 \(X_i\) 看作有向图中的节点,权值看作边,求单源最短路的过程结束后,自然保证了所有约束条件的成立(无解的情况除外)。

差分约束系统最重要的是如何构造,构造方法大体有:

  • 将最优解表示为前缀的形式,这样才能利用到区间的差分性质。
  • 考虑最优解前缀的单调性,即:是否隐含着后一项必须大于前一项。
  • 对于本题来说,还需要考虑每个位置的点只能被选择一次。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;

inline int read(){
	int x=0,f=1;char ch;
	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
	return f*x;
}

struct node{
	int nxt,to,w;
}e[maxn<<2];
int tot=1,head[maxn];
inline void add_edge(int from,int to,int w){
	e[++tot]=(node){head[from],to,w},head[from]=tot;
}
int n,bl,br,d[maxn];
queue<int> q;
bool in[maxn];

void read_and_parse(){
	n=read(),bl=1e8,br=-1e8;
	for(int i=1;i<=n;i++){
		int l=read()+1,r=read()+1,c=read();
		bl=min(bl,l),br=max(br,r);
		add_edge(l-1,r,c);
	}
	for(int i=bl;i<=br;i++)add_edge(i-1,i,0),add_edge(i,i-1,-1);
}

void spfa(){
	fill(in+bl,in+br+1,0);
	fill(d+bl,d+br+1,-1e9);
	d[bl-1]=0,in[bl-1]=1,q.push(bl-1);
	while(q.size()){
		int u=q.front();q.pop(),in[u]=0;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to,w=e[i].w;
			if(d[v]<d[u]+w){
				d[v]=d[u]+w;
				if(!in[v])in[v]=1,q.push(v);
			}
		}
	}
}

void solve(){
	spfa();
	printf("%d\n",d[br]);
}
void init(){
	memset(head,0,sizeof(head)),tot=1;
}

int main(){
	int T=read();
	while(T--){
		init();
		read_and_parse();
		solve();
	}
	return 0;
} 
posted @ 2019-03-21 14:00  shellpicker  阅读(118)  评论(0编辑  收藏  举报