传送门:【HDU】4735 Little Wish~ lyrical step~
题目分析:对每个点dfs一次找到他能在不超过长度D内遍历到的节点,link一下,然后跑DLX算法,不断更新ans,ans的意义即在女孩位置上的男孩数。
代码如下:
题目分析:对每个点dfs一次找到他能在不超过长度D内遍历到的节点,link一下,然后跑DLX算法,不断更新ans,ans的意义即在女孩位置上的男孩数。
代码如下:
#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;
typedef long long LL ;
#pragma comment ( linker , "/STACK:1024000000" )
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define rec( i , A , o ) for ( int i = A[o] ; i != o ; i = A[i] )
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 55 ;
const int MAXE = 5005 ;
const int MAXNODE = 2505 ;
const int INF = 0x3f3f3f3f ;
struct Edge {
int v , c , n ;
Edge () {}
Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {}
} ;
struct DLX {
int L[MAXNODE] ;
int R[MAXNODE] ;
int D[MAXNODE] ;
int U[MAXNODE] ;
int row[MAXNODE] ;
int col[MAXNODE] ;
int H[MAXN] ;
int S[MAXN] ;
int n ;
int boy[MAXN] ;
int boy_size ;
int size ;
int vis[MAXN] , Time ;
int ans ;
void init ( int _n ) {
n = _n ;
Time = 0 ;
boy_size = 0 ;
clr ( H , -1 ) ;
clr ( vis , 0 ) ;
clr ( boy , 0 ) ;
For ( i , 0 , n ) {
S[i] = 0 ;
U[i] = D[i] = i ;
L[i] = i - 1 ;
R[i] = i + 1 ;
}
L[0] = n ;
R[n] = 0 ;
size = n ;
ans = INF ;
}
void link ( int r , int c ) {
++ S[c] ;
++ size ;
row[size] = r ;
col[size] = c ;
D[size] = c ;
U[size] = U[c] ;
D[U[c]] = size ;
U[c] = size ;
if ( ~H[r] ) {
L[size] = L[H[r]] ;
R[size] = H[r] ;
R[L[size]] = size ;
L[R[size]] = size ;
} else L[size] = R[size] = H[r] = size ;
}
void remove ( int c ) {
rec ( i , D , c ) {
R[L[i]] = R[i] ;
L[R[i]] = L[i] ;
}
}
void resume ( int c ) {
rec ( i , U , c ) R[L[i]] = L[R[i]] = i ;
}
int h () {
++ Time ;
int cnt = 0 ;
rec ( i , R , 0 ) if ( vis[i] != Time ) {
vis[i] = Time ;
++ cnt ;
rec ( j , D , i ) rec ( k , R , j ) vis[col[k]] = Time ;
}
return cnt ;
}
void dance ( int d , int cnt ) {
if ( cnt >= ans || d + h () > boy_size ) return ;
if ( !R[0] ) {
ans = cnt ;
return ;
}
int c = R[0] ;
rec ( i , R , 0 ) if ( S[i] < S[c] ) c = i ;
rec ( i , D , c ) {
remove ( i ) ;
rec ( j , R , i ) remove ( j ) ;
dance ( d + 1 , cnt + !boy[row[i]] ) ;
rec ( j , L , i ) resume ( j ) ;
resume ( i ) ;
}
}
} ;
DLX dlx ;
Edge E[MAXE] ;
int H[MAXN] , cntE ;
int n , D ;
void clear () {
cntE = 0 ;
clr ( H , -1 ) ;
}
void addedge ( int u , int v , int c ) {
E[cntE] = Edge ( v , c , H[u] ) ;
H[u] = cntE ++ ;
}
void dfs ( int u , int root , int fa = 0 , int d = 0 ) {
dlx.link ( root , u ) ;
for ( int i = H[u] ; ~i ; i = E[i].n ) {
int v = E[i].v , c = E[i].c ;
if ( v == fa ) continue ;
if ( d + c <= D ) dfs ( v , root , u , d + c ) ;
}
}
void solve () {
int u , v , c ;
clear () ;
scanf ( "%d%d" , &n , &D ) ;
dlx.init ( n ) ;
For ( i , 1 , n ) {
scanf ( "%d" , &dlx.boy[i] ) ;
dlx.boy_size += dlx.boy[i] ;
}
rep ( i , 1 , n ) {
scanf ( "%d%d%d" , &u , &v , &c ) ;
addedge ( u , v , c ) ;
addedge ( v , u , c ) ;
}
For ( i , 1 , n ) dfs ( i , i ) ;
dlx.dance ( 0 , 0 ) ;
printf ( "%d\n" , dlx.ans == INF ? -1 : dlx.ans ) ;
}
int main () {
int T , cas = 0 ;
scanf ( "%d" , &T ) ;
while ( T -- ) {
printf ( "Case #%d: " , ++ cas ) ;
solve () ;
}
return 0 ;
}