zoukankan      html  css  js  c++  java
  • POJ 1201 Intervals (经典) (差分约束)

    <题目链接>

    题目大意:
    给你$n$段区间,$a_i,b_i,c_i$ 表示在 $[a_i,b_i]$ 区间内至少要选择$c_i$个点。现在问你在满足这n个条件的情况下,最少要选多少个点?

    解题分析:

    经典的差分约束。本问题需要满足的不等式有:$s[b[i]]-s[a[i]-1]geq c[i],0leq s[i]-s[i-1]leq 1$,其中s[i]表示到第i个位置为止,所选择的点的个数。

    转换一下,就能够得到:

    $s[b[i]]geq s[a[i]-1]+c[i]$

    $s[i]geq s[i-1]+0$

    $s[i-1]geq s[i]+(-1)$    以上转载于 >>>

    差分约束不等式与最短(长)路结合的评价标准就是:如果不等式的约束条件是"<=",比如b-a<=n,就是将其在图中转化为add(a,b,n),然后跑最短路,因为那个式子能够转化为 b<=a+n ,这与最短路松弛操作中的三角形不等式 (dis[v]<=dis[u]+w,最终目地的三角形不等式)类似,这里的b就相当于v,a相当于u,所以是a--->b连边。

    同理,如果是b-a>=n,就是a--->b连边,然后跑最长路,需要注意的是,由于边权在差分约束中很有可能出现负数,所以一般用SPFA求解最短(长)路。

    比如本题就是用SPFA求最长路。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=5e4+7;
    int n,st,ed,cnt;
    int head[N],dis[N];
    bool vis[N];
    struct Edge{
        int to,val,nxt;
        Edge(int _to=0,int _val=0,int _nxt=0):to(_to),val(_val),nxt(_nxt){}
    }edge[N<<2];
    queue<int>q;
    inline void add(int u,int v,int w) {
        edge[++cnt]=Edge(v,w,head[u]);
        head[u]=cnt;
    }
    void spfa(){        //利用spfa求最长路
        memset(dis,-0x3f,sizeof(dis));
        q.push(st);
        vis[st]=true;dis[st]=0;
        while(q.size()){
            int u=q.front();q.pop();
            vis[u]=false;
            for(int i=head[u];~i;i=edge[i].nxt){
                int v=edge[i].to;
                if(dis[v]<dis[u]+edge[i].val){    
                    dis[v]=dis[u]+edge[i].val;
                    if(!vis[v])q.push(v),vis[v]=true;
                }
            }
        }
    }
    int main(){
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        st=1e9,ed=-1;
        for(int i=1;i<=n;i++){
            int a,b,c;scanf("%d%d%d",&a,&b,&c);
            add(a-1,b,c);        //s[b]-s[a-1]>=c
            st=min(st,a-1);ed=max(ed,b);
        }
        for(int i=st;i<=ed;i++){     //根据添加的两个约束条件建边
            add(i-1,i,0);       //s[i]-s[i-1]>=0
            add(i,i-1,-1);        //s[i]-s[i-1]<=1 即 s[i-1]-s[i]>=-1 
        }
        spfa();    //因为是">=",与最长路的松弛方式(三角形不等式)相同
        printf("%d
    ",dis[ed]);
    }

      

  • 相关阅读:
    Excel生成二维折线图详细教程 TheChosen
    sql语句截取字段中某一符号前几位的方法? TheChosen
    python快速下载包的镜像源? TheChosen
    Android 超大图长图浏览库 SubsamplingScaleImageView 源码解析
    记录线上APP一个排序比较引发的崩溃 Comparison method violates its general contract!
    Android 内存泄漏检测工具 LeakCanary(Kotlin版)的实现原理
    改数组长度
    枚举数组所有组合
    Ubuntu20.04启动后光标一直闪烁
    harbor镜像仓库清理操作
  • 原文地址:https://www.cnblogs.com/00isok/p/10557955.html
Copyright © 2011-2022 走看看