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

测试地址: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 1000000000
using 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;
}
原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793586.html