zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    selenium headlesschrome下设置最大窗口模式
    lxml简明教程
    lxml etree的一个问题
    pycharm导入模块的时候遇到的两个错误
    linux下安装python
    【Android进阶学习】shape和selector的结合使用
    ANDROID资源文件【转】
    android 屏幕适配问题【转】
    android UI进阶之style和theme的使用
    Android入门第十六篇之Style与Theme [转]
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3196858.html
Copyright © 2011-2022 走看看