POJ 1716 Integer Intervals 差分约束系统

/**
 * @file main.cpp
 * @brief 差分约束系统,也可以用贪心来做
 *        贪心的方法是按照[a,b]的b进行排序,然后贪心
 *
 *        差分约束条件为
 *        1. s[b] - s[a] >= 2
 *        2. s[i] - s[i - 1] >= 0
 *        3. s[i] - s[i - 1] <= 1
 *
 *        即转换为
 *        1. if (s[a] + 2 > s[b])
 *              s[b] = s[a] + 2
 *        2. if (s[i - 1] + 0 > s[i])
 *              s[i] = s[i - 1] + 0
 *        3. if (s[i] + (-1) > s[i - 1])
 *              s[i - 1] = s[i] + (-1)
 *
 *        因此,构图为:
 *        1. (a, b)添加权为2的边
 *        2. (i - 1, i)添加权为0的边
 *        3. (i, i - 1)添加权为-1的边
 *
 *
 * @author yekeren
 * @version 1.0.0
 * @date 2013-06-06
 */


#include <iostream>
#include <queue>


#define MAX_INT 0x7fffffff
#define LIMIT 10002


///(M)临接表
struct edge_t {
    int b, c;
    struct edge_t *next;
};


edge_t *k[LIMIT] = { NULL };
edge_t pool[LIMIT * 4];
int npool = 0;


/**
 * @brief 临接表添加边 
 * @param a
 * @param b
 * @param c
 */
void add_edge(int a, int b, int c)
{
    pool[npool].b = b;
    pool[npool].c = c;
    pool[npool].next = k[a];


    k[a] = &pool[npool++];
}


/**
 * @brief shortest path faster algorithm 
 * @param imin
 * @param imax
 * @return   
 */
int spfa(int imin, int imax)
{
    int s[LIMIT] = { 0 };
    for (int i = 0; i <= imax; ++i) {
        s[i] = - MAX_INT;
    }


    unsigned char visit[LIMIT] = { 0 };
    std::queue<int> q;


    visit[imin] = 1;
    q.push(imin);


    s[imin] = 0;


    while (!q.empty())
    {
        int u = q.front();
        visit[u] = 0;
        q.pop();


        for (edge_t *p = k[u]; p != NULL; p = p->next)
        {
            int v = p->b;
            int c = p->c;


            if (s[u] + c > s[v]) 
            {
                s[v] = s[u] + c;


                if (!visit[v]) 
                {
                    visit[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return s[imax];
}


int main(int argc, char *argv[])
{
    int n;
    std::cin >> n;


    int imax = 0;
    int imin = MAX_INT;


    for (int i = 0; i < n; ++i)
    {
        int a, b;
        std::cin >> a >> b;


        ++b;
        if (a < imin) {
            imin = a;
        }
        if (b > imax) {
            imax = b;
        }


        add_edge(a, b, 2);
    }


    for (int i = imin; i < imax; ++i)
    {
        add_edge(i, i + 1, 0);
        add_edge(i + 1, i, -1);
    }


    std::cout << spfa(imin, imax) << std::endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值