zoukankan      html  css  js  c++  java
  • ZOJ4028 LIS(差分约束)

    图中给出了不等式关系并求可行解,考虑使用差分约束来解决。

    差分约束的基本套路是:

    1.找全不等关系

    2.找到一个点可以遍历全图

    3.对于可行解问题,跑最短路,一般上我们定义>=关系式

    对于本题的关系式,为了控制l<=ai<=r,我们用一个超级点去连

    对于fi的限制,有两种情况,前面有和他长度相等的,这样前一个必须大于等于后一个。

    第二种是我们必须大于f[i]-1。

    对于这两种情况,只需要维护一个last数组表示最靠近当前位置的每个长度的位置

    为什么只需要维护这个就能找全关系呢?因为对于第一种,他是一个递减的,因此只要最靠近的大于他,前面的都大于他

    对于第二种情况,因为我们只需要大于前面最小的,就能满足题意,所以也只需要找最靠近他的

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=1e6+10;
    const int inf=0x3f3f3f3f;
    int h[N],ne[N],e[N],w[N],idx;
    int n,f[N],l[N],r[N];
    int last[N];
    int st[N];
    ll dis[N];
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
    }
    void spfa(){
        queue<int> q;
        q.push(n+1);
        dis[n+1]=0;
        for(int i=1;i<=n+1;i++)
            st[i]=0;
        st[n+1]=1;
        while(q.size()){
            auto t=q.front();
            q.pop();
            st[t]=0;
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(dis[j]>dis[t]+w[i]){
                    dis[j]=dis[t]+w[i];
                    if(!st[j]){
                        q.push(j);
                        st[j]=1;
                    }
                }
            }
        }
        for(int i=1;i<n;i++)
            cout<<dis[i]<<" ";
        cout<<dis[n]<<endl;
    }
    int main(){
        ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            cin>>n;
            int i;
            idx=0;
            for(i=0;i<=n+1;i++){
                h[i]=-1;
                last[i]=0;
                dis[i]=1e18;
            }
            for(i=1;i<=n;i++){
                cin>>f[i];
            }
            for(i=1;i<=n;i++){
                cin>>l[i]>>r[i];
            }
            for(i=1;i<=n;i++){
                add(i,n+1,-l[i]);
                add(n+1,i,r[i]);
                if(last[f[i]]){
                    add(last[f[i]],i,0);
                }
                if(f[i]){
                    add(i,last[f[i]-1],-1);
                }
                last[f[i]]=i;
            }
            spfa();
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    [转]fedora国内源常见配置
    [转]Fedora 添加国内源(sohu, 163)
    keepalived
    lvs详解
    ansible详解
    练习题:计算传入字符串中的【数字】、【字母】、【空格】和【其他】的个数
    面向对象(继承、重写、多态)以及异常处理
    面向对象详解以及封装案例解答
    进程、线程与GIL全局解释器锁详解
    python函数与模块(paramiko、socket模块、文件处理、装饰器、迭代器等)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13757332.html
Copyright © 2011-2022 走看看