poj 1716 -- Integer Intervals ( 差分约束 )

这个可能用贪心也能做 , 没想那么多 , 觉得差分约束复杂度可以接受就水下了

由于点的范围有0 , 要把所有点的值加1 , 用dis [ i ] 表示从0 到 i 一共有多少个元素 , 还要注意隐藏条件和注意事项,

代码中会标出。

# include <cstdio>
# include <iostream>
# include <set>
# include <map>
# include <vector>
# include <list>
# include <queue>
# include <stack>
# include <cstring>
# include <string>
# include <cstdlib>
# include <cmath>
# include <algorithm>

using namespace std ;

struct Edge
{
    int v , w , next ;
} edge [ 31000 ] ;
int cnt ;
int dis [ 11000 ] ;
int head [ 11000 ] ;

void addedge ( int u , int v , int w )
{
    edge [ cnt ] . v = v ;
    edge [ cnt ] . w = w ;
    edge [ cnt ] . next = head [ u ] ;
    head [ u ] = cnt ++ ;
}

int spfa ( )
{
    queue < int > q ;
    bool vis [ 11000 ] = { 0 } ;
    for ( int i = 0 ; i <= 10001 ; i ++ )
    {
        q . push ( i ) ;
        vis [ i ] = 1 ;
    }
    while ( q . size ( ) )
    {
        int u = q . front ( ) ;
        q . pop ( ) ;           //以前习惯把这个删除操作放在循环后面, 但有一次让判断负环WA了好久
        vis [ u ] = 0 ;         //后来才发现顶点可能与自身连边,放后面就处理不了这种情况, 当然这道题不存在这种可能
        for ( int i = head [ u ] ; i != -1 ; i = edge [ i ] . next )
        {
            int v = edge [ i ] . v ;
            int w = edge [ i ] . w ;
            if ( dis [ u ] + w < dis [ v ] )
            {
                dis [ v ] = dis [ u ] + w ;
                if ( ! vis [ v ] )
                {
                    vis [ v ] = 1 ;
                    q . push ( v ) ;
                }
            }
        }
    }
    return dis [ 10001 ] - dis [ 0 ] ;
}

int main ( )
{
    cnt = 0 ;
    memset ( head , -1 , sizeof ( head ) ) ;
    int n ;
    scanf ( "%d" , & n ) ;
    while ( n -- )
    {
        int a , b ;
        scanf ( "%d%d" , & a , & b ) ;
        addedge ( b + 1 , a , -2 ) ;    // 加边操作
    }
    for ( int i = 0 ; i <= 10000 ; i ++ )
    {
        addedge ( i , i + 1 , 1 ) ;   //隐藏的两个条件 , 所以数组要开成 3 * maxn
        addedge ( i + 1 , i , 0 ) ;   //
    }
    cout << spfa ( ) << endl ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值