POJ 1201 Intervals 差分约束系统建图

title

POJ 1201
CH POJ1201
Description

You are given n closed, integer intervals [ai, bi] and n integers c1, …, cn.
Write a program that:
reads the number of intervals, their end points and integers c1, …, cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,…,n,
writes the answer to the standard output.

Input

The first line of the input contains an integer n (1 <= n <= 50000) – the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.

Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,…,n.

Sample Input

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output

6

Source

Southwestern Europe 2002

analysis

嗯,看完书上的文字题解,不出十分钟敲完,然后。。。。。。。我承认,我把“负权”两个字忘掉了,傻子一般地敲了一个 D i j k s t r a Dijkstra Dijkstra,然后半天跑不出来答案,再好好看书后,猛然发现,这是有负权的。。。。。。。。。。

这道题其实就是让我们在 0 ∼ 50 , 000 0\sim50,000 050,000之间选出尽量少的数,使得每一个 [ a i , b i ] [a_{i},b_{i}] [aibi]内至少有 c i c_{i} ci个数被选择。

s [ k ] s[k] s[k]表示 0 ∼ k 0\sim k 0k之间有几个数字被选,很明显, s [ b i ] − s [ a i − 1 ] > = c i s[b_{i}]-s[a_{i}-1]>=c_{i} s[bi]s[ai1]>=ci。这就很明确地告诉我们这是一个差分约束系统的模型了。

当然,秉着差分约束经常搞些隐含条件的规则,我们还是要去再想想的,毕竟这样才能保证求出的解是合法的。

然后我们就可以发现(你管我是怎么发现的QWQ):
1 . s [ k ] − s [ k − 1 ] > = 0 .s[k]-s[k-1]>=0 .s[k]s[k1]>=0 0 ∼ k 0 \sim k 0k中所选取的整数肯定要比 0 ∼ k − 1 0\sim k-1 0k1中选取的整数多。
2. s [ k ] − s [ k − 1 ] < = 1 s[k]-s[k-1]<=1 s[k]s[k1]<=1。因为每个数最多只能被选择一次。也可变形成为 s [ k − 1 ] − s [ k ] > = − 1 s[k-1]-s[k]>=-1 s[k1]s[k]>=1

因此,我们把 0 ∼ 50001 0 \sim 50001 050001 50002 50002 50002个整数分别作为图中的节点,从每个 k − 1 k-1 k1 k k k连一条长度为 0 0 0的有向边, k k k k − 1 k-1 k1连一条长度为 − 1 -1 1的有向边,从每个 a i a_{i} ai b i + 1 b_{i}+1 bi+1连一条长度为ci的有向边。

最后,令 s [ 0 ] = 0 s[0]=0 s[0]=0,以 0 0 0为起点跑单源最长路。因为本题保证了 1 < = c i < = b i − a i + 1 1 <= c_{i} <= b_{i} - a_{i}+1 1<=ci<=biai+1,所以本题中没有正环,差分约束系统一定有解。求完最长路后, s [ 50001 ] = d i s t [ 50001 ] s[50001]=dist[50001] s[50001]=dist[50001]就是本题的答案。(到这里,也就知道了 s [ ] s[] s[]就是 d i s t [ ] dist[] dist[]了,而且,《算阶》上的因为要从 − 1 -1 1开始跑,我搞不定,就把他们全都加一了。)。

code

#include
using namespace std;
const int maxn=1e7+10;
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1,ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}
int ver[maxn],edge[maxn],Next[maxn],head[maxn],len;
inline void add(int x,int y,int z)
{
	ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int dist[maxn];
bool vis[maxn];
inline void Dijkstra(int s)
{
	queue<int>q;
	memset(dist,-1,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[s]=0,vis[s]=1;
	q.push(s);
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int i=head[x];i;i=Next[i])
		{
			int y=ver[i],z=edge[i];
			if (dist[y]<dist[x]+z)
			{
				dist[y]=dist[x]+z;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
}
int main()
{
	int n,mx=-1;
	read(n);
	for (int i=1;i<=n;++i)
	{
		int x,y,z;
		read(x);read(y);read(z);
		add(x,y+1,z);
		mx=max(y,mx);
	}
	++mx;
	for (int i=1;i<=mx;++i)
		add(i-1,i,0),add(i,i-1,-1);
	Dijkstra(0);
	printf("%d\n",dist[mx]);
	return 0;
}

你可能感兴趣的:(差分约束系统,======图论=======,POJ,CH)