您的位置:首页 > 其它

POJ 1201 Intervals 差分约束

2017-04-18 14:21 573 查看
链接:http://poj.org/problem?id=1201

Intervals

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 23123Accepted: 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.

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: