【HDU】4735 Little Wish~ lyrical step~ 重复覆盖

传送门:【HDU】4735 Little Wish~ lyrical step~

题目分析:对每个点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 ;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值