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
",spfa());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wangfang20/p/3196858.html