POJ 1201 Intervals 差分约束
链接:http://poj.org/problem?id=1201
Intervals
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 23123 | Accepted: 8728 |
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
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
题意:
给你n个闭区间
【a,b】 及c
要求区间内的点数必需要大于等于c
点仅仅存在于区间内。
然后问负无穷到正无穷最多有多少点。
做法:
我们从最左边到最右边。
区间内最少有c个点,说明点(a-1)到b点 最少会添加c个点。
也就是说 b-(a-1)>=c 转换下 (a-1)-b<=-c 就是差分约束的公式了。
然后就是建边 建一条权值为-c 的b到(a-1)的边即可了。
然后取最小的坐标x,取最大的坐标d。
由于求最大值 所以得公式 d-(x-1)>=?
加个负号, (x-1)-d<=-?
,所以最后最短路 计算 d点到(x-1)的最短距离。然后取负就是答案了。
可是这样条件还不够。
还有关键的是相邻点之间的建边。设相邻两点 (i) 和(i+1)
走到(i+1)数到的点数 肯定是比左边的(i)要大的 , 所以 (i+1)-(i)>=0 加个负号, (i)-(i+1)<=0
而从(i)走到(i+1)最多仅仅添加了一个点。所以(i+1)-(i)<=1 。
所以还要建这些边,才干跑出最后的答案。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <stack> #include <queue> #include <vector> #include <deque> #include <set> #include <map> #define VM 60000 #define EM 160005 #define inf 0x7f7f7f7f int head[VM],ep; struct edge { int v,w,next; }e[EM]; void addedge(int cu,int cv,int cw) { ep ++; e[ep].v = cv; e[ep].w = cw; e[ep].next = head[cu]; head[cu] = ep; } int spfa (int n,int sta,int ee) { int vis[VM],stack[VM],dis[VM],vn[VM]; memset(vis,0,sizeof(vis)); memset(dis,inf,sizeof dis); //for(int i=1;i<=n;i++) //dis[i]=-inf; memset(vn,0,sizeof vn); vn[sta]=1; dis[sta] = 0; vis[sta] = 1; int top = 1; stack[0] = sta; while (top) { int u = stack[--top]; if(vn[u]>n) return -inf; vis[u] = 0; for (int i = head[u];i != -1;i = e[i].next) { int v = e[i].v; if (dis[v] > dis[u] + e[i].w) { dis[v] = dis[u] + e[i].w; if (!vis[v]) { vis[v] = 1; vn[v]++; stack[top++] = v; } } } } return dis[ee]; } int main () { int n,m,v1,v2,cost; int ml,md; while(scanf("%d",&n)!=EOF) { ep = 0; memset (head,-1,sizeof(head)); int minn=999999; int maxx=0; for(int i=0;i<n;i++) { int u,v,lim; scanf("%d%d%d",&u,&v,&lim); //v-u<=lim u++; v++; maxx=max(maxx,v); minn=min(minn,u); addedge(v,u-1,-lim);// v-(u-1)>=lim (u-v)<=lim } //for(int i=0;i<50001;i++) for(int i=minn-1;i<maxx;i++) { addedge(i+1,i,0);//(i)-(i+1)《=0 后面的点数大 addedge(i,i+1,1);//(i+1)-(i)《=1 i+1 最多放一个 } /* for(int i=1;i<n;i++) { addedge(i+1,i,0);//dian(i)- dian(i+1)<=0 }*/ int ans=spfa(maxx-minn+2,maxx,minn-1); if(ans==-inf) puts("-1");//负环 有矛盾条件 else if(ans==inf)//两者能够无线远 puts("-2"); else printf("%d\n",-ans); } return 0; }