poj 1201 Intervals 差分约束系统+SPFA 给出一些区间, 告诉每个区间中至少需要取Ci个数。求出满足n个条件的集合C的最少的元素个数

Intervals
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 12353 Accepted: 4558

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
 
 

/思路: //题目的转换真的非常非常巧妙,让我再来梳理一下。本题的题意是给了我们一些区间, //然后告诉每个区间中至少需要取Ci个数。求出满足n个条件的集合C的最少的元素个数。

//首先第一个转化,是找到一个合理的表示。用ti表示每一个数,如果有用就是1,否则是0。 //把S(i+1)定义成集合C中小于i+1的元素的个数。S[i+1]表示从0到i有多少个数是需要的。 //因此,题目中的条件可以表示成S[bi+1]>=S[ai]+Ci//至少要Ci个 //这与bellman中的松弛操作时很像的。因此可以看成一些点有D[v]>=D[u]+w(u,v) //上式对任何u成立,所以v应该是里面最大的,若D[v]<D[u]+w(u,v)则D[v]=D[u]+w(u,v) //于是。可以从ai和bi+1连一条线,它的长度是ci这里只有这些条件还是不够的, //还要加上两个使其满足整数性质的条件1>=s[i+1]-s[i]>=0有了这么多条件,使其自然构成 //了一个差分约束系统。用spfa算法得到一个最长路,第一个到最后一个节点的最长路即是需要求的值。

 

 

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const __int64 maxn=1001000; const __int64 inf=(__int64)1<<62; struct edge//邻接表 { __int64 t,w;//s->t=w; __int64 next;//数组模拟指针 }; __int64 p[maxn];//邻接表头节点 edge G[maxn];//邻接表 __int64 V,E;//点数[1-n] 边数 __int64 dis[maxn]; __int64 que[maxn],fro,rear;//模拟队列 __int64 vis[maxn]; __int64 inque[maxn];//入队次数 bool spfa(__int64 s0) { fro=rear=0; for(__int64 i=0;i<=V;i++) dis[i]=inf;dis[s0]=0; memset(vis,0,sizeof(vis)); memset(inque,0,sizeof(inque)); que[rear++]=s0;vis[s0]=1;inque[s0]++; while(fro!=rear) { __int64 u=que[fro];fro++; if(fro==maxn) fro=0; vis[u]=0; for(__int64 i=p[u];i!=-1;i=G[i].next) { __int64 s=u,t=G[i].t,w=G[i].w; if(dis[t]>dis[s]+w) { dis[t]=dis[s]+w; if(vis[t]==0) { que[rear++]=t,vis[t]=1; inque[t]++; if(inque[t]>V) return false; if(rear==maxn) rear=0; } } } } return true; } int main() { __int64 ci; while(scanf("%I64d",&ci)==1) { V=0,E=0; memset(p,-1,sizeof(p)); __int64 src=maxn,det=-1;//最小,大值 while(ci--) { __int64 u,v,w;scanf("%I64d%I64d%I64d",&u,&v,&w);v++; if(u<src) src=u; if(v>det) det=v; //v->u=-w; G[E].t=u; G[E].w=-w; G[E].next=p[v]; p[v]=E++; } for(__int64 i=1;i<det;i++) { //i->i+1=1; __int64 u=i,v=i+1,w=1; G[E].t=v; G[E].w=w; G[E].next=p[u]; p[u]=E++; //i+1->i=0; u=i+1,v=i,w=0; G[E].t=v; G[E].w=w; G[E].next=p[u]; p[u]=E++; } V=det; //增加源点0 for(int i=1;i<=V;i++) { __int64 u=0,v=i,w=0; //0->i=0; G[E].t=v; G[E].w=w; G[E].next=p[u]; p[u]=E++; } spfa(0);//找源点到其他点的最短距离 printf("%I64d/n",dis[det]-dis[src]); } return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值