POJ1201(Hdu1384) Intervals差分约束系统
2015-11-17 15:44
477 查看
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 endpoints 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 <= 50 000) - 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 <= 50 000 and 1 <= ci <= bi - ai + 1.Process to the end of file.
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 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6题意大概是这样:有n个区间[Ai,Bi],有一个集合Z,集合Z和每个区间至少有Ci个相同元素;求这个集合至少有多少个元素。
定义dis
数组记录区间[0,n]的最少有多少个元素在集合z内,则可以建立一个不等式:dis[Bi+1]-dis[Ai]>=Ci;
另外由题意有:0<=dis[i+1]-dis[i]<=1;(因为i可能从0开始所以不使用i-1和i)
因此有:
dis[i+1]-dis[i]>=0;
dis[i]-dis[i+1]>=-1;
因为是求最小值,所以是计算最长路。
边数比较多而且有负边所以使用spfa算法。
代码如下:
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<queue> #define INF 1<<29 using namespace std; struct node { int to,len,next; }edge[200050]; int head[50010],used[50010],dis[50010],inqueue[50010],k,n,minx,maxx; void add_edge(int st,int en,int len) { edge[k].to=en; edge[k].len=len; edge[k].next=head[st]; head[st]=k++; } void init() { memset(used,0,sizeof(used)); memset(inqueue,0,sizeof(inqueue)); memset(head,-1,sizeof(head)); minx=INF,maxx=-1; for(int i=1;i<=n;i++) { int st,en,len; scanf("%d%d%d",&st,&en,&len); minx=min(minx,st); maxx=max(maxx,en+1); add_edge(st,en+1,len); } for(int i=minx;i<=maxx;i++) { add_edge(i,i+1,0); add_edge(i+1,i,-1); } } void spfa(int st,int time) { for(int i=minx;i<=maxx;i++) dis[i]=-INF; queue<int>q; dis[st]=0; used[st]=1; q.push(st); inqueue[st]++; while(!q.empty()) { int top=q.front(); q.pop(); used[top]=0; for(int j=head[top];j!=-1;j=edge[j].next) { if(dis[edge[j].to]<dis[top]+edge[j].len) { dis[edge[j].to]=dis[top]+edge[j].len; if(!used[edge[j].to]) { used[edge[j].to]=1; if(++inqueue[edge[j].to]>time-1) { printf("%d\n",dis[maxx]); } q.push(edge[j].to); } } } } printf("%d\n",dis[maxx]); } int main() { while(scanf("%d",&n)!=EOF) { k=0; init(); spfa(minx,maxx-minx+1); } return 0; }
相关文章推荐
- 从今天开始
- GCD应用拓展
- Linux中__init、__devinit等初始化宏解析和入口函数
- 谈谈css中px , em,及rem
- 字符串转化为日期格式 并可以再次格式化得到的日期
- 关于ojdbc6与class12那些事
- ACM常用模板——数论
- mysql 主从设置
- 矩阵连乘基础
- tomcat发布工程后,WEB-INF/classes下文件不编译的解决方法
- 使用BIOS中断和汉字库显示汉字
- hdoj 计算球体积
- Agile.Net 组件式开发平台 - 组件开发示例
- JPA聚合函数(适用于联合查询)
- Xcode插件失效解决
- iOS 公司开发者账号申请
- Android EventBus源码解析 带你深入理解EventBus
- iOS开发笔记--UILabel的相关属性设置
- TCP/IP详解之:ARP协议 和 RARP协议
- sql之left join、right join、inner join的区别