【POJ1201】Intervals-差分约束系统+单源最长路

来源:互联网 发布:苹果音频编辑软件 编辑:程序博客网 时间:2024/06/07 06:45

测试地址:Intervals
题目大意:有一个集合,给定n个三元组[ai,bi,ci],表示集合包含区间[ai,bi]中的至少ci个整数,求这个集合最少可能包含的整数个数。
做法:本题需要用到差分约束系统和单源最长路。
题目中给了形如bik=aitkci这样的一堆条件,其中tk表示k在不在集合中,如果在,tk=1,否则tk=0。我们可以对t求一个前缀和,令Si=ik=1tk,则上面的条件都可以写成SbiSai1ci的形式了,这就可以用差分约束系统建图了,从一个新建的源点向其他所有点连一条边权为0的边,然后从原点求一遍单源最长路,Smax(bi)的最小值就是它对应顶点的最长路值了,这个值也是要求的答案。如果不明白为什么,建议还是先去了解差分约束系统的定义吧……
等等,好像有什么东西漏了。注意到ti的取值并不是任意的,它的取值范围是0ti1,也就是说题目还有隐含的条件:0SiSi11,这个条件可以拆成SiSi10Si1Si1两个条件,那么在原来建的图上再添上这些边,求出来的就是正确的答案了。
有的同学可能会问了,会不会存在无解的情况?可以证明,根据题目的数据范围,建出来的图是不会出现正环的,也就是一定有解,所以不用担心。
以下是本人代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#define inf 1000000000using namespace std;int n,maxlen=0,s,first[50010]={0},tot=0;int dis[50010];bool vis[50010]={0};struct edge {int v,d,next;} e[300010];queue <int> Q;void insert(int a,int b,int d){    e[++tot].v=b;    e[tot].d=d;    e[tot].next=first[a];    first[a]=tot;}void spfa(int s){    Q.push(s);    vis[s]=1;dis[s]=0;    for(int i=0;i<=maxlen+1;i++) dis[i]=-inf;    while(!Q.empty())    {        int v=Q.front();Q.pop();        for(int i=first[v];i;i=e[i].next)            if (dis[e[i].v]<dis[v]+e[i].d)            {                dis[e[i].v]=dis[v]+e[i].d;                if (!vis[e[i].v]) Q.push(e[i].v);            }        vis[v]=0;    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        maxlen=max(maxlen,b);        insert(a,b+1,c);    }    s=maxlen+2;    for(int i=0;i<=maxlen;i++)    {        insert(s,i+1,0);        if (i>0)        {            insert(i+1,i,-1);            insert(i,i+1,0);        }    }    spfa(s);    printf("%d",dis[maxlen+1]);    return 0;}
原创粉丝点击