poj 1201 差分约束

http://www.cnblogs.com/wangfang20/p/3196858.html

题意:

求集合Z中至少要包含多少个元素才能是每个区间[ai,bi]中的元素与Z中的元素重合个数为ci。

思路:对于dis[b]-dis[a]>=c的形式,我们建一条a到b的边,权值为c,最后求最长路就是要得到的最小值。

可举一例,[1,8]假使有7个不同的数,[1,4]假使有2个不同的数,[4,8]假使有3个不同的数,都满足f[8]-f[1]>=7,f[4]-f[1]>=2,f[8]-f[4]>=3.若求最短路,那么肯定得到的结果是5,与f[8]-f[1]>=7相矛盾。故求得是最长路,得到7就是最小的结果。

可是紧紧这样建边,并不能将每个离散的点整合到一个图中,对于任何一个单元区间,1=>f[i+1]-f[i]>=0,故我们就可以得到两个式子f[i+1]-f[i]>=0与f[i]-f[i+1]>=-1;

最后根据式子建边,求差分约束。

要注意的是要将右边界+1,。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<queue>

#define inf 1<<30

#define Maxn 51000

#define Maxm 500000

using namespace std;

int dis[Maxn],vi[Maxn],minn,maxn,index[Maxn],e,Que[1000010];

struct Edge{

    int to,next,val;

}edge[Maxm];

void init()

{

    for(int i=0;i<=Maxn-1;i++)

        dis[i]=-inf;

    memset(vi,0,sizeof(vi));

    memset(index,-1,sizeof(index));

    e=maxn=0;

    minn=inf;

}

void addedge(int from,int to,int val)

{

    edge[e].to=to;

    edge[e].val=val;

    edge[e].next=index[from];

    index[from]=e++;

}

int spfa()

{

    int i,j,temp,head,rear;

    head=rear=0;

    Que[head++]=minn;

    dis[minn]=0;

    //cout<<maxn<<endl;

    while(head!=rear)

    {

        temp=Que[rear++];

        //cout<<temp<<endl;

        vi[temp]=0;

        for(i=index[temp];i!=-1;i=edge[i].next)

        {

            int now=edge[i].to;

            if(dis[now]<dis[temp]+edge[i].val)

            {    dis[now]=dis[temp]+edge[i].val;

                if(!vi[now])

                    Que[head++]=now;

                vi[now]=1;

            }

        }

    }

    return dis[maxn];

}

int main()

{

    int i,j,n,a,b,c;

    while(scanf("%d",&n)!=EOF)

    {

        init();

        //cout<<"ok"<<endl;

        for(i=1;i<=n;i++)

        {

            scanf("%d%d%d",&a,&b,&c);

            b++;

            minn=min(minn,a);

            maxn=max(maxn,b);

            addedge(a,b,c);

        }

        for(i=minn;i<maxn;i++)

        {

            addedge(i,i+1,0);

            addedge(i+1,i,-1);

        }

        printf("%d\n",spfa());

    }

    return 0;

}

 

你可能感兴趣的:(差分约束)