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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    搭建无线漫游网络及需要注意的问题
    手机如何借用笔记本网络上网
    VM下Linux网卡丢失(pcnet32 device eth0 does not seem to be ...)解决方案
    安装VMware vCenter过程设置数据库方法
    无法连接vCenter Server清单https://IP:10443
    ESXi控制台TSM:弥补vSphere Client不足
    Shell中逻辑判断
    bash 编程中循环语句用法
    Shell中IFS用法
    Shell中的${},##和%%的使用
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13757332.html
Copyright © 2011-2022 走看看