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;
    }
  • 相关阅读:
    centos7.6 安装与配置 MongoDB yum方式
    MongoDB 介绍
    centos 关闭selinux
    前端 HTML标签属性
    前端 HTML 标签嵌套规则
    前端 HTML 标签分类
    前端 HTML body标签相关内容 常用标签 表单标签 form里面的 input标签介绍
    前端 HTML body标签相关内容 常用标签 表单标签 form 表单控件分类
    前端 HTML form表单标签 select标签 option 下拉框
    POJ 1426
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3196858.html
Copyright © 2011-2022 走看看