• poj 1201 Intervals(差分约束)


    做的第一道差分约束的题目,思考了一天,终于把差分约束弄懂了O(∩_∩)O哈哈~

    题意(略坑):三元组{ai,bi,ci},表示区间[ai,bi]上至少要有ci个数字相同,其实就是说,在区间[0,50000]上,每一个三元组表示[ai,bi]之间至少要标记ci个数字,问至少要标记多少个数字。

    在学习差分约束的童鞋,建议看一下:09年姜碧野的《SPFA算法的优化及应用》,06年冯威的《浅析差分约束系统》,不过后者看起来较难搞懂,也可以看http://ycool.com/post/m2uybbf 写的很不错。

    这里写一下我自己的一点心得:

    1、差分约束求的是什么?

      这里分为两种:求值,判环。

      求值:如这道题所示,最终求的是整个区间上被标记点的最小数量,也就是从起点到终点的最小值,不需考虑判环的情况。更广泛的讲,它可以求解不等式的一组解。

      判环:poj 1364判断存不存在,即判正负环。

    2、差分约束中的松弛操作

      举个最短路的例子,1->2 c=3,1->3 c=1,3->2 c=1,即以1为起点,d[2]>d[3]+w(3,2),可以进行松弛。而三条边本身表示的是:a(2)-a(1)<=3,a(3)-a(1)<=1,a(2)-a(3)<=1,我们是从d[]=INF一路更新过来的,用1->3->2这条边更新1->2,实际上表示的是后两个不等式之和a(2)-a(1)<=2比第一个不等式的约束条件更强。

    3、最长路与最短路的区别

      两者不仅是在三角不等式的表现形式上不同,具体求解的值也不同。

      首先要明确,需要额外的一个限定条件:一般为加入源点s,并建立权值为0的边。对于一个不等式组来说,只要有一组解,那么同时加上定值k,仍然满足约束条件。

      最短路:d[v]<d[u]+w(u,v),d[i]初始化为INF,而求解出来的是不等式的最大值。何为最大值?若确定其中一个的值,并非能得到每个数的定值,因为是不等式,所以每个值有其取值范围。这里的最大值就是在源点s的限定条件内,所能够取值的上界。仔细思考,这里的最短路只是满足不等式组条件所找到的解,由于最短路是由大到小做松弛操作,找到的最短路即为“最大”。

      最长路:d[v]>d[u]+w(u,v),d[i]初始化为-INF,解释同上。这道题目求的是最小值,自然就只能由最长路求解。

    4、关于点的数量

      如题目所示{ai,bi,ci},[ai,bi]上至少标记ci个点,可以转化为:s(bi)-s(ai-1)>=ci,注意是(ai-1)而非(ai),由于减1的关系,总点数+1。

      在判环过程中,SPFA的判定条件为入队n次,其实质是最短路最长经过(n-1)条边,所以入队n次队列仍不为空,即可以判定存在正负环。当点的总数+1,对应的SPFA判环的条件也就变更为cnt[]>n。

    5、关于图的连通性

      无论是求值,还是判环,原图不构成强连通的前提下都是不能搜索到每一个点的,所以才出现设立一个源点s的方法。事实上,能够到达各个点,更加实用的是在SPFA初始化时,就把所有点加入队列,并把d[i]全部初始化为0。不仅仅是解决了连通的问题,更是避免了错误——加上一个源点s,使总点数为(n+2),SPFA的判环条件必须为cnt[]>(n+1),这是很容易忽视的问题。

      这道题由于存在所谓的隐藏条件0<=s(i)-s(i-1)<=1,据此建图已经能够实现图上的连通。

    6、不等式的变形

      差分约束解决的是>=和<=的问题,若题目给出的是>k(或<k),需要变形。比如若k是整数,>k等价于>=k+1。

    7、无穷解,无解。

      http://www.cnblogs.com/zstu-abc/archive/2013/08/18.html

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 #define rep(i,a,b) for(int i=a;i<=b;i++)
     6 #define clr(a,m) memset(a,m,sizeof(a))
     7 using namespace std;
     8 
     9 const int MAXN=55555;
    10 const int INF =MAXN;
    11 
    12 struct Edge{
    13     int v,c,next;
    14     Edge(){}
    15     Edge(int _v,int _c,int _next):v(_v),c(_c),next(_next){}
    16 }edge[MAXN<<2];
    17 
    18 int head[MAXN],tol;
    19 int d[MAXN],inq[MAXN];
    20 
    21 void init()
    22 {
    23     tol=0;
    24     clr(head,-1);
    25 }
    26 
    27 void add(int u,int v,int c)
    28 {
    29     edge[tol]=Edge(v,c,head[u]);
    30     head[u]=tol++;
    31 }
    32 
    33 void SPFA(int down,int up)
    34 {
    35     queue<int>q;
    36     clr(inq,0);
    37     rep(i,down,up)
    38         if(i==down)d[i]=0;
    39         else d[i]=-INF;
    40     q.push(down);
    41     inq[down]=true;
    42     while(!q.empty())
    43     {
    44         int u=q.front();q.pop();
    45         inq[u]=false;
    46         for(int i=head[u];i!=-1;i=edge[i].next)
    47         {
    48             int v=edge[i].v;
    49             int c=edge[i].c;
    50             if(d[v]<d[u]+c){
    51                 d[v]=d[u]+c;
    52                 if(!inq[v]){
    53                     q.push(v);
    54                     inq[v]=true;
    55                 }
    56             }
    57         }
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     int n,up=0,down=MAXN;
    64     int u,v,c;
    65     scanf("%d",&n);
    66 
    67     init();
    68     rep(i,1,n){
    69         scanf("%d%d%d",&u,&v,&c);
    70         add(--u,v,c);
    71         up=max(up,v);
    72         down=min(down,u);
    73     }
    74     rep(i,down,up){
    75         add(i-1,i,0);
    76         add(i,i-1,-1);
    77     }
    78     SPFA(down,up);
    79 
    80     printf("%d
    ",d[up]);
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    面向对象程序设计六大原则
    获取View的快照
    Xcode调试之exc_bad_access以及 message sent to deallocated instance
    OOA/OOD/OOP
    检测网络是否有效
    图像IO
    iOS应用性能调优的25个建议和技巧
    iOS围绕某点缩放或旋转的AnchorPoint的设定
    NPOI导出Excel2007板
    不同三级域名与二级域名之间互相共享Cookie
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3277305.html
Copyright © 2020-2023  润新知