解题报告 之 POJ1201 Intervals
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.
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
53 7 38 10 36 8 11 3 110 11 1
Sample Output
6
我不得不说一开始没读懂题。。。后来终于懂了。。。
题目大意:给N个闭区间,对每个[ai,bi] 任意取ci个数,最终将取出来的数组成一个集合S,根据互异性,求S中最少有几个元素。这道题乍一看觉得比较变态。。。根据提示学习了一下差分约束系统。差分约束系统主要用于解决求解多个约束不等式下的解的问题。系统中,有n个变量,m个约束。约束形如xj-xi<=bk,于是乎就可以联想到最短路中的d[v]-d[u]<=w[u,v]。系统的要么无解要么有无数组解,所以我们可以通过Bellmen-Ford算法或者是SPFA算法来求得一组解。
关于初始化dis的问题:
1.如果将源点到各点的距离初始化为0,最终求出的最短路满足 它们之间相互最接近了。
2.如果将源点到各点的距离初始化为INF(无穷大),其中之1为0,最终求出的最短路满足 它们与该点之间相互差值最大。
于是乎这道题的话就是用dis[i]表示到i之前一共选了几个。于是乎得到约束方程dis[bi]-dis[ai]>=ci;还有两个隐讳的约束,就是dis[i+1]-dis[i]<=1已经dis[i+1]-dis[i]>=0 .
约束条件标准形式 : dis[ai]<=dis[bi]-ci;
dis[i+1]-dis[i]<=1;
dis[i]-dis[i+1]<=0;
所以用Bellmen-Ford算法每次更新三个约束的值,直到不更新为止。(此题不会出现负权回路的情况所以无需担心),最后答案就是d[max-bi]-d[min-ai] , 所以d[i]的初始值不重要,到最后都会剪掉。
感觉是很久以前的题了,于是还是写上来了。
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 50010
#define INF 1000000
struct edge
{
int u, v, w;
};
edge edges[MAXN];
int n, dis[MAXN], ms, me;
void bellmen_ford()
{
bool flag=true;
while (flag)
{
flag = false;
for (int i = 1; i <= n; i++)
{
if (dis[edges[i].u] > dis[edges[i].v] - edges[i].w)
{
dis[edges[i].u] = dis[edges[i].v] - edges[i].w;
flag = true;
}
}
for (int i = ms; i <= me; i++)
{
if (dis[i] > dis[i - 1] + 1)
{
dis[i] = dis[i - 1] + 1;
flag = true;
}
}
for (int i = me; i >= ms; i--)
{
if (dis[i - 1] > dis[i])
{
dis[i - 1] = dis[i];
flag = true;
}
}
}
}
int main()
{
while (scanf("%d", &n) == 1)
{
ms = INF;
me = -1;
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].w);
ms = min(ms, edges[i].u);
me = max(me, edges[i].v);
dis[i] = i;
edges[i].u--;
}
bellmen_ford();
printf("%d\n", dis[me] - dis[ms - 1]);
}
return 0;
}
感觉是很久以前的题了,于是还是写上来了。