这个可能用贪心也能做 , 没想那么多 , 觉得差分约束复杂度可以接受就水下了
由于点的范围有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 ;
}