大家都很强, 可与之共勉 。
题意:
给定实直线
L
上
对于给定的开区间集合
题解:
把答案看作是
既然是点可以重合,那么可以不拆点(其实拆点也可以的)。
因为是
k
条路径,所以从源点到一号点连一条容量为
画画图很好理解的
# include <bits/stdc++.h>
template < class T > inline bool chkmax ( T& d, const T& x ) { return d < x ? ( d = x ), 1 : 0 ; }
template < class T > inline bool chkmin ( T& d, const T& x ) { return d > x ? ( d = x ), 1 : 0 ; }
# define oo 0x3f3f3f3f
# define N 1050
# define M 5050
class MaxCostMaxFlow {
private :
struct edge {
int to, nxt, w, cost ;
} g [M << 1] ;
int S, T ;
int head [N], dis [N], pre [N], ecnt ;
inline bool spfa ( int S, int T ) {
static std :: bitset < N > inq ;
static std :: deque < int > Q ;
inq.reset ( ) ; Q.clear ( ) ;
memset ( pre, 0, sizeof ( int ) * ( T + 1 ) ) ;
memset ( dis, -1, sizeof ( int ) * ( T + 1 ) ) ;
Q.push_front ( S ) ;
inq [S] = 1 ;
dis [S] = 0x3f3f3f3f ;
while ( ! Q.empty ( ) ) {
int u = Q.front ( ) ; Q.pop_front ( ) ;
inq [u] = 0 ;
for ( int i = head [u] ; i ; i = g [i].nxt ) {
int& v = g [i].to ;
if ( g [i].w && chkmax ( dis [v], dis [u] + g [i].cost ) ) {
pre [v] = i ;
if ( ! inq [v] ) {
( Q.empty ( ) || dis [v] > dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ;
inq [v] = 1 ;
}
}
}
}
return ( bool ) pre [T] ;
}
public :
MaxCostMaxFlow ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; }
inline void clear ( ) {
ecnt = 1 ; memset ( head, 0, sizeof head ) ;
}
inline void add_edge ( int u, int v, int w, int cost ) {
g [++ ecnt] = ( edge ) { v, head [u], w, cost } ; head [u] = ecnt ;
g [++ ecnt] = ( edge ) { u, head [v], 0, -cost } ; head [v] = ecnt ;
}
std :: pair < int, int > mcmf ( int S, int T ) {
this -> S = S, this -> T = T ;
int flow = 0, cost = 0, x ;
while ( spfa ( S, T ) ) {
x = oo ;
for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) chkmin ( x, g [i].w ) ;
for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) {
g [i].w -= x, g [i ^ 1].w += x ;
cost += x * g [i].cost ;
}
flow += x ;
}
return std :: make_pair ( flow, cost ) ;
}
} Lazer ;
int dust [N] ;
int l [N], r [N], val [N] ;
# undef N
# undef M
int main ( ) {
int n, k ;
scanf ( "%d%d", & n, & k ) ;
const int S = 2 * n + 1, T = 2 * n + 2 ;
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%d%d", l + i, r + i ) ;
if ( l [i] > r [i] ) std :: swap ( l [i], r [i] ) ;
dust [( i << 1 ) - 1] = l [i], dust [i << 1] = r [i] ;
val [i] = ( r [i] - l [i] ) ;
}
std :: sort ( dust + 1, dust + n + n + 1 ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
l [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, l [i] ) - dust ;
r [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, r [i] ) - dust ;
}
Lazer.add_edge ( S, 1, k, 0 ), Lazer.add_edge ( 2 * n, T, k, 0 ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
Lazer.add_edge ( l [i], r [i], 1, val [i] ) ;
}
for ( int i = 1 ; i < 2 * n ; ++ i ) {
Lazer.add_edge ( i, i + 1, oo, 0 ) ;
}
printf ( "%d\n", Lazer.mcmf ( S, T ).second ) ;
return 0 ;
}
还有一种建图(边数复杂度是一样的):
# include <bits/stdc++.h>
template < class T > inline bool chkmax ( T& d, const T& x ) { return d < x ? ( d = x ), 1 : 0 ; }
template < class T > inline bool chkmin ( T& d, const T& x ) { return d > x ? ( d = x ), 1 : 0 ; }
# define oo 0x3f3f3f3f
# define N 1050
# define M 5050
class MaxCostMaxFlow {
private :
struct edge {
int to, nxt, w, cost ;
} g [M << 1] ;
int S, T ;
int head [N], dis [N], pre [N], ecnt ;
inline bool spfa ( int S, int T ) {
static std :: bitset < N > inq ;
static std :: deque < int > Q ;
inq.reset ( ) ; Q.clear ( ) ;
memset ( pre, 0, sizeof ( int ) * ( T + 1 ) ) ;
memset ( dis, -1, sizeof ( int ) * ( T + 1 ) ) ;
Q.push_front ( S ) ;
inq [S] = 1 ;
dis [S] = 0x3f3f3f3f ;
while ( ! Q.empty ( ) ) {
int u = Q.front ( ) ; Q.pop_front ( ) ;
inq [u] = 0 ;
for ( int i = head [u] ; i ; i = g [i].nxt ) {
int& v = g [i].to ;
if ( g [i].w && chkmax ( dis [v], dis [u] + g [i].cost ) ) {
pre [v] = i ;
if ( ! inq [v] ) {
( Q.empty ( ) || dis [v] > dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ;
inq [v] = 1 ;
}
}
}
}
return ( bool ) pre [T] ;
}
public :
MaxCostMaxFlow ( ) { ecnt = 1 ; memset ( head, 0, sizeof head ) ; }
inline void clear ( ) {
ecnt = 1 ; memset ( head, 0, sizeof head ) ;
}
inline void add_edge ( int u, int v, int w, int cost ) {
g [++ ecnt] = ( edge ) { v, head [u], w, cost } ; head [u] = ecnt ;
g [++ ecnt] = ( edge ) { u, head [v], 0, -cost } ; head [v] = ecnt ;
}
std :: pair < int, int > mcmf ( int S, int T ) {
this -> S = S, this -> T = T ;
int flow = 0, cost = 0, x ;
while ( spfa ( S, T ) ) {
x = oo ;
for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) chkmin ( x, g [i].w ) ;
for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] ) {
g [i].w -= x, g [i ^ 1].w += x ;
cost += x * g [i].cost ;
}
flow += x ;
}
return std :: make_pair ( flow, cost ) ;
}
} Lazer ;
int dust [N] ;
int l [N], r [N], val [N] ;
# undef N
# undef M
int main ( ) {
int n, k ;
scanf ( "%d%d", & n, & k ) ;
const int S = 2 * n + 5, T = 2 * n + 6 ;
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%d%d", l + i, r + i ) ;
if ( l [i] > r [i] ) std :: swap ( l [i], r [i] ) ;
dust [( i << 1 ) - 1] = l [i], dust [i << 1] = r [i] ;
val [i] = ( r [i] - l [i] ) ;
}
std :: sort ( dust + 1, dust + n + n + 1 ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
l [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, l [i] ) - dust ;
r [i] = std :: lower_bound ( dust + 1, dust + 1 + n + n, r [i] ) - dust ;
}
const int S1 = 2 * n + 1, T1 = 2 * n + 2 ;
Lazer.add_edge ( S, S1, k, 0 ), Lazer.add_edge ( T1, T, k, 0 ) ;
for ( int i = 1 ; i <= 2 * n ; ++ i ) {
Lazer.add_edge ( S1, i, 1, 0 ), Lazer.add_edge ( i, T1, 1, 0 ) ;
}
for ( int i = 1 ; i <= n ; ++ i ) {
Lazer.add_edge ( l [i], r [i], 1, val [i] ) ;
}
for ( int i = 1 ; i < 2 * n ; ++ i ) {
Lazer.add_edge ( i, i + 1, oo, 0 ) ;
}
printf ( "%d\n", Lazer.mcmf ( S, T ).second ) ;
return 0 ;
}