POJ 1201 差分约束(链式前向星

来源:互联网 发布:766冒险岛数据库进不了 编辑:程序博客网 时间:2024/06/05 04:44
Intervals
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 26192 Accepted: 10015

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

53 7 38 10 36 8 11 3 110 11 1

Sample Output

6



很有收获的一道题,感觉对差分约束的理解更深了一点。

题意:平面上有n个区间,第i个区间的左端点为ai,右端点为bi。然后求一个最短长度的集合z,使该集合在每一个区间[ai,bi],都至少有ci个点在区间中。求z集合的长度。

思路:一开始的思路是贪心,很明显可以将区间按右端点排序,然后每个区间就从最右边开始选m个点(m为ci - 该区间已经被选的点的个数,m<=0时,则该区间可以不选。)。优化可以用一个线段树或树状数组维护。


但既然是在学差分约束,当然还是用差分约束系统来做。


开始一直没有思路,因为我以前遇见的都是求最大值,最小值并不知道怎么入手。

然后看了网上的一个博客,才知道:

求最大值: 方程变形为:  a - b <= c ,b->a,权边为c。 求最短路
求最小值:  方程变形为: b - a >= -c,a->b,权边为-c。求最长路


然后还有一个关键点在于,如果要得到正确答案,必须保证相邻点连通。

因为:
 0 <=  a[i+1] - a[i]  <= 1

然后两点之间加两条边即可。




#include <iostream>#include <cstdio>#include <cstdlib>#include<cstring>#include <string>#include <algorithm>#include <cmath>#include <cctype>#include<queue>#include<map>using namespace std;typedef long long ll;const int maxn = 50000 + 100;const int INF = 1e8;struct P{int v,w,next;}G[maxn*20];int head[maxn],out[maxn],dis[maxn],vis[maxn];int n,tot;void init(void){tot = 0;memset(head,-1,sizeof(head));}void add(int u,int v,int w){G[tot].v = v;G[tot].w = w;G[tot].next = head[u];head[u] = tot++;}int spfa(int st,int ed){queue<int> que;for(int i=0 ;i<=ed ;i++){dis[i] = -INF;vis[i] = 0;out[i] = 0;}dis[st] = 0;vis[st] = 1;que.push(st);while(que.size()){int u = que.front();que.pop();vis[u] = 0;for(int i=head[u] ;i!=-1 ;i=G[i].next){int v = G[i].v,w = G[i].w;if(dis[u] + w > dis[v]){dis[v] = dis[u] + w;if(!vis[v]){vis[v] = 1;que.push(v);}}}}return dis[ed];}void solve(int u,int v){printf("%d\n",spfa(u,v));}int main(){while(scanf("%d",&n) != EOF){init();int a,b,c;int u=maxn,v=0;while(n--){scanf("%d%d%d",&a,&b,&c);add(a,b+1,c);u = min(u,a);v = max(v,b+1);}for(int i=0 ;i<=v ;i++){add(i+1,i,-1);add(i,i+1,0);}solve(u,v);}return 0;} 







0 0
原创粉丝点击