POJ1201-Intervals(差分约束)

63 篇文章 0 订阅
52 篇文章 0 订阅

Intervals
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 27284 Accepted: 10474

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



题意:有n个区间,每个区间有3个值,ai,bi,ci代表,在区间[ai,bi]上至少要选择ci个整数点,ci可以在区间内任意取不重复的点,问最少选多少个点能够满足

解题思路: 差分约束问题,根据题意可以得到每个前缀和建一个点s[bi]-s[ai-1]>=ci,同时要满足前缀和的性质,即:s[i]-s[i-1]>=0,s[i]-s[i-1]<=1(关于有向边和权值的确定:不管是求最短路(上界,最大值)还是最长路(下界,最小值),先把式子统一化成 X-Y<=C的形式。如果要求的是最大值(最短路),那么就建立<Y,X>的有向边,权值为C;如果要求的是最小值(最长路),那么就建立<X,Y>的有向边,权值为-C)


#include <iostream>    
#include <cstdio>    
#include <string>    
#include <cstring>    
#include <algorithm>    
#include <cmath>    
#include <vector>    
#include <map>    
#include <set>    
#include <queue>    
#include <stack>    
#include <functional>    
#include <climits>    

using namespace std;

#define LL long long    
const int INF = 0x3f3f3f3f;

int s[50005],nt[4* 50005],e[4*50005],w[4*50005];
int dis[50005], vis[50005], n;

void SPFA(int ss)
{
	memset(dis, -INF, sizeof dis);
	dis[ss] = 0;
	queue<int>q;
	q.push(ss);
	while (!q.empty())
	{
		int pre = q.front(); q.pop();
		vis[pre] = 0;
		for (int i = s[pre]; ~i; i=nt[i])
		{
			int ee = e[i];
			if (dis[ee] < dis[pre] + w[i])
			{
				dis[ee] = dis[pre] + w[i];
				if (!vis[ee])
				{
					q.push(ee);
					vis[ee] = 1;
				}
			}
		}
	}
}

int main()
{
	while (~scanf("%d", &n))
	{
		int u, v, ww, cnt = 0;
		memset(s, -1, sizeof s);
		int mi = INF,ma = -INF;
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d%d", &u, &v, &ww);
			nt[cnt] = s[u], s[u] = cnt, e[cnt] = v+1,w[cnt++] = ww;
			mi = min(mi, u);
			ma = max(ma, v + 1);
		}
		for (int i = mi; i < ma; i++)
		{
			nt[cnt] = s[i], s[i] = cnt, e[cnt] = i + 1, w[cnt++] = 0;
			nt[cnt] = s[i + 1], s[i+1] = cnt, e[cnt] = i, w[cnt++] = -1;
		}
		SPFA(mi);
		printf("%d\n", dis[ma]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值