POJ1201 Intervals

来源:互联网 发布:qq三国70js一套小鬼神 编辑:程序博客网 时间:2024/06/05 19:34

差分约束

题目传送门

题目大意:给你n个区间及每个区间取的元素个数ci,求出最少需要多少个元素才能满足每个区间取的元素个数。

利用强大的差分约束#(手动滑稽)

既然要求最小值,那么就是跑最长路喽!

首先,我们不难发现前两个条件:0 <= s[i] - s[i-1] <= 1。转化成a - b >= c的形式:s[i]-s[i-1]>=0,s[i-1]-s[i]>=-1。
羊后根据输入——在a到b的区间中至少有c个元素——就能够找到第三个条件: s[b] - s[a-1] >= c。但是由于a>=0,当a=0时数组会炸掉。因此我们要把所有的元素+1,也就是s[b+1] - s[a] >= c。

羊后spfa跑个最长路就好啦!

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct edge{    int next;    int to;    int dis;};int n,k,mi=0x7fffffff,ma;int a,b,c;int s[50005];edge ed[200005];int h[50005];int dis[50005];int que[1000000];bool f[50005];void read(int x,int y,int z){    ed[k].next=h[x];    ed[k].to=y;    ed[k].dis=z;    h[x]=k;    k++;}int main(){    scanf("%d",&n);    memset(h,-1,sizeof(h));    for (int i=0;i<n;i++){        scanf("%d%d%d",&a,&b,&c);        read(a,b+1,c);        mi=min(mi,a);        ma=max(ma,b+1);    }    for (int i=mi;i<ma;i++){        read(i,i+1,0);        read(i+1,i,-1);        dis[i]=-0x7fffffff;    }    dis[ma]=-0x7fffffff;    dis[mi]=0;    int r=0,w=1;    que[1]=mi; f[mi]=true;    while (r<w){        int x=que[++r];        f[x]=false;        for (int i=h[x];i!=-1;i=ed[i].next){            if (!f[ed[i].to]&&dis[ed[i].to]<dis[x]+ed[i].dis){                f[ed[i].to]=true;                dis[ed[i].to]=dis[x]+ed[i].dis;                que[++w]=ed[i].to;            }        }    }    printf("%d",dis[ma]);    return 0;}
原创粉丝点击