poj 1201 Intervals(第一道差分约束题)

呃,这是我做的第一道差分约束题,想先谈谈我对差分约束的理解,由于本人能力有限,可能理解有点浅显。如果您已看过相关讲解,请无视之。。。。

1、想看的是百度百科和维基百科上对差分约束的的定义,上面都举了同一个例子,就是,寻找一个5个向量x=(xi)以满足下列8个差分约束条件:

x1-x2≤0 ,x1-x5≤-1 ,x2-x5≤1 ,x3-x1≤5 ,x4-x1≤4 ,x4-x3≤-1 ,x5-x3≤-3 ,x5-x4≤-3

然后讲了用Bellman_ford求最短路的方法来实现差分约束。

2、然后,看了这道题,本以为会是一道裸的差分约束题,想了一会,很是没思路,很没“骨气”的查了解题报告,结果又了解了一点知识,那就是通过最短路径算法求出来的一组解当中,所有未知数都达到最大值,由此有查到了一篇讲差分约束很好的Blog,http://imlazy.ycool.com/post.1702305.html里面讲的很详细,而且也简单的证明了上面那句话,虽然没想出具体方法验证,但是他的讲解还是让我明白了这个结论。个人觉得这篇Blog让我受益最大。

还有下面这个对这题的讲解最详细

http://blog.csdn.net/morgan_xww/article/details/6359229

但是http://blog.csdn.net/guzhilei1986/article/details/2305137做法更简单。

下面说说这题吧。

题意:给出N个区间以及每个区间对应的整数,计算一个有最小元素个数的集合,使得对于每个给出的区间,集合与它的相同元素个数不小于相应的整数。

思路:呃, 首先要承认,这题的思路真不是自己的思路,参考了解题报告。假设,dis[i+1] 代表源点到xi 点的满足题目中要求的最少的点数,因此可以得出不等式dis[j] - dis[i-1] >= ci;

即dis[j] >= dis[i-1] + ci,有这个不等式我们很容易想到单源最短路,但是上面说咯额,通过最短路方法求出的一组解中,所有未知数都达到最大值,题目中要求的是从s点到t点的最少数目的点,所以我们要改为求最长路,为什么要这样,可以参考第一Blog中的讲解。但是只有上面的不等式是不够得,题目中还有一个隐藏的要求, 即0<= dis[j+1] - dis[j] <= 1 ,由此可以求出满足要求的最少的点。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#define N  50005
#define M 100000
#define INF 0xffff
using namespace std ;

struct node
{
    int s ;
    int e ;
    int val ;
}p[N] ;

int dis[M] ;
int minn , maxx ;

int Bellman_ford ( int n )
{
    int i , j , flag ;

    for ( i = minn ; i <= maxx ; i++ )
    dis[i] = -INF;
    dis[minn] = 0 ;

    for ( i = 0 ; i <= maxx - minn ; i++ )
    {
        flag = 0 ;
        for ( j = 1 ; j <= n ; j++ )
        {
            if ( dis[p[j].s] != -INF && dis[p[j].s] + p[j].val > dis[p[j].e] )
            {
                dis[p[j].e] = dis[p[j].s] + p[j].val ;
                flag = 1 ;
            }
        }
        for ( j = minn ; j < maxx ; j++ )
        {
            if ( dis[j] != -INF && dis[j] > dis[j+1] )
            {
                dis[j+1] = dis[j] ;
                flag = 1 ;
            }
        }
        for ( j = maxx ; j > minn ; j-- )
        {
            if ( dis[j] != -INF && dis[j] - 1 > dis[j-1] )
            {
                dis[j-1] = dis[j] - 1;
                flag = 1 ;
            }
        }
        if ( !flag )
        break;
    }
    return dis[maxx] ;
}

int main()
{
    int n , i ;

    while ( scanf ( "%d" , &n ) != EOF )
    {
        minn = INF ;
        maxx = -INF ;
        for ( i = 1 ; i <= n ; i++ )
        {
            scanf ( "%d%d%d" , &p[i].s , &p[i].e , &p[i].val );
            p[i].e++ ;
            if ( p[i].s < minn )
            minn = p[i].s ;
            if ( p[i].e > maxx )
            maxx = p[i].e ;
        }
        printf ( "%d\n" , Bellman_ford( n ));
    }
    return 0 ;
}

 

posted @ 2012-07-21 11:27  Misty_1  阅读(232)  评论(0编辑  收藏  举报