A
A
A
令两类点集合为
S
,
T
S,T
S , T ,考虑最后的图一定形如一堆
S
,
T
S,T
S , T 的连通块以及若干
S
S
S 其中每个
S
S
S 连了若干个
T
T
T ,对这个进行
d
p
dp
d p ,记
d
p
i
,
j
dp_{i,j}
d p i , j 表示两类点大小下的图个数,枚举连通块转移,
O
(
n
4
)
O(n^4)
O ( n 4 )
#include<bits/stdc++.h>
#define cs const
# define pb push_back
using namespace std ;
cs int Mod = 1e9 + 7 ;
int add ( int a , int b ) { return a + b > = Mod ? a + b - Mod : a + b ; }
int dec ( int a , int b ) { return a - b < 0 ? a - b + Mod : a - b ; }
int mul ( int a , int b ) { return 1 ll * a * b % Mod ; }
void Add ( int & a , int b ) { a = add ( a , b ) ; }
void Mul ( int & a , int b ) { a = mul ( a , b ) ; }
void Dec ( int & a , int b ) { a = dec ( a , b ) ; }
int ksm ( int a , int b ) { int as = 1 ; for ( ; b ; b > > = 1 , Mul ( a , a ) ) if ( b & 1 ) Mul ( as , a ) ; return as ; }
cs int N = 105 ;
int T , n , m , C [ N ] [ N ] , pw [ N ] ;
int dp [ N ] [ N ] , f [ N ] [ N ] ;
void work ( int n ) {
for ( int i = 0 ; i < = n ; i + + ) C [ i ] [ 0 ] = 1 ;
for ( int i = 1 ; i < = n ; i + + )
for ( int j = 1 ; j < = n ; j + + )
C [ i ] [ j ] = add ( C [ i- 1 ] [ j- 1 ] , C [ i- 1 ] [ j ] ) ;
pw [ 0 ] = 1 ; for ( int i = 1 ; i < = n ; i + + )
pw [ i ] = add ( pw [ i- 1 ] , pw [ i- 1 ] ) ;
for ( int i = 1 ; i < = n ; i + + ) f [ i ] [ 0 ] = 1 ;
for ( int i = 1 ; i < = n ; i + + )
for ( int j = 1 ; i + j < = n ; j + + )
f [ i ] [ j ] = mul ( f [ i ] [ j- 1 ] , mul ( dec ( pw [ i ] , 1 ) , pw [ j- 1 ] ) ) ;
for ( int i = 0 ; i < = n ; i + + )
dp [ i ] [ 0 ] = ksm ( 2 , i * ( i- 1 ) > > 1 ) ;
static int h [ N ] ; h [ 0 ] = 1 ;
for ( int i = 1 ; i < = n ; i + + )
for ( int j = 1 ; j < = i ; j + + )
Add ( h [ i ] , mul ( h [ i-j ] , C [ i- 1 ] [ j- 1 ] ) ) ;
for ( int i = 0 ; i < = n ; i + + )
dp [ 0 ] [ i ] = h [ i ] ;
static int z [ N ] ; z [ 0 ] = 1 ;
for ( int i = 1 ; i < = n ; i + + ) {
z [ i ] = dp [ i ] [ 0 ] ;
for ( int j = 1 ; j < i ; j + + )
Dec ( z [ i ] , mul ( C [ i- 1 ] [ j- 1 ] , mul ( z [ j ] , dp [ i-j ] [ 0 ] ) ) ) ;
}
for ( int i = 1 ; i < = n ; i + + )
for ( int j = 1 ; j < = n ; j + + )
Mul ( f [ i ] [ j ] , z [ i ] ) ;
for ( int i = 1 ; i < = n ; i + + )
for ( int j = 1 ; i + j < = n ; j + + ) {
for ( int k = 1 ; k < = i ; k + + )
for ( int l = 1 ; l < = j ; l + + )
Add ( dp [ i ] [ j ] , mul ( mul ( C [ i ] [ k ] , C [ j- 1 ] [ l- 1 ] ) , mul ( dp [ i-k ] [ j-l ] , f [ k ] [ l ] ) ) ) ;
for ( int k = 1 ; k < = j ; k + + )
Add ( dp [ i ] [ j ] , mul ( dp [ i ] [ j-k ] , C [ j- 1 ] [ k- 1 ] ) ) ;
}
}
int main ( ) {
# ifdef FSYolanda
freopen ( "1.in" , "r" , stdin ) ;
# endif
work ( 100 ) ; scanf ( "%d" , & T ) ; while ( T-- )
scanf ( "%d%d" , & n , & m ) , cout < < dp [ n-m ] [ m ] < < '\n' ;
return 0 ;
}
B
B
B
考虑最后分为三类点,中间一段的是有贡献的 最小割建图,考虑割与
S
S
S 表示前缀,割
T
T
T 的表示后缀,拆点,割中间的表示在中间 对于限制,连边
(
a
,
b
)
,
(
a
′
,
b
′
)
(a,b),(a',b')
( a , b ) , ( a ′ , b ′ ) 表示
a
a
a 的段在
b
b
b 之前
#include<bits/stdc++.h>
#define cs const
# define pb push_back
using namespace std ;
cs int N = 1e4 + 50 ;
cs int INF = 1e9 + 7 ;
int fi [ N ] , nxt [ N ] , to [ N ] , w [ N ] , ec = 1 ;
void adde ( int x , int y , int z ) {
nxt [ ++ec ] = fi [ x ] , fi [ x ] = ec , to [ ec ] = y , w [ ec ] = z ;
nxt [ ++ec ] = fi [ y ] , fi [ y ] = ec , to [ ec ] = x , w [ ec ] = 0 ;
}
int n , m , a [ N ] , S , T ;
int d [ N ] ;
bool bfs ( ) {
memset ( d , - 1 , sizeof ( d ) ) ; d [ S ] = 0 ;
queue < int > q ; q . push ( S ) ;
while ( ! q . empty ( ) ) {
int x = q . front ( ) ; q . pop ( ) ;
for ( int e = fi [ x ] , v ; e ; e = nxt [ e ] )
if ( w [ e ] & & d [ v=to [ e ] ] = = - 1 ) {
d [ v ] = d [ x ] + 1 ; q . push ( v ) ;
if ( v = = T ) return true ;
}
} return false ;
}
int dfs ( int u , int flw ) {
if ( u = = T ) return flw ; int ans = 0 ;
for ( int e = fi [ u ] , v ; e ; e = nxt [ e ] )
if ( d [ v=to [ e ] ] = = d [ u ] + 1 ) {
int dlt = dfs ( v , min ( flw , w [ e ] ) ) ;
w [ e ] - = dlt ; w [ e ^ 1 ] + = dlt ;
ans + = dlt ; flw- = dlt ; if ( ! flw ) break ;
} if ( flw ) d [ u ] = - 1 ; return ans ;
}
int dinic ( ) { int flw = 0 ; while ( bfs ( ) ) flw + = dfs ( S , INF ) ; return flw ; }
int main ( ) {
# ifdef FSYolanda
freopen ( "1.in" , "r" , stdin ) ;
# endif
scanf ( "%d%d" , & n , & m ) ;
for ( int i = 1 ; i < = n ; i + + )
scanf ( "%d" , & a [ i ] ) ;
S = 0 , T = n + n + 1 ;
for ( int i = 1 , u , v ; i < = m ; i + + )
scanf ( "%d%d" , & u , & v ) , adde ( u , v , INF ) , adde ( u + n , v + n , INF ) ;
int ans = 0 ;
for ( int i = 1 ; i < = n ; i + + ) {
if ( a [ i ] < 0 ) adde ( i , i + n , -a [ i ] ) ;
if ( a [ i ] > 0 ) adde ( S , i , a [ i ] ) , adde ( i + n , T , a [ i ] ) , ans + = a [ i ] ;
} cout < < ans-dinic ( ) < < '\n' ;
return 0 ;
}