传送门:【HDU】5046 Airport
题目分析:DLX的模板题。。。二分最长长度,然后建边跑DLX,如果选择不超过K的方案存在则调整上界,否则调整下界。就这么简单,当然可以用rabbit巨巨告诉我的一个方法优化二分次数:直接找到所有的距离对,离散后将距离对按照升序排列在数组里,然后二分的时候直接二分数组下标即可,因为最多只有1800项,比直接二分距离复杂度小了太多太多。。
今天我实在是傻逼。。。以为不写高度函数没有关系。。。结果最后就因为这个TLE了。。更傻逼的是TLE了后还没想去加高度函数。。。T U T。。赛后加了就AC了,怎么会有我这么2的人呢。。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> //using namespace std ; typedef long long LL ; #pragma comment(linker, "/STACK:16777216") #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 travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next ) #define clr( a , x ) memset ( a , x , sizeof a ) #define cpy( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , n const int MAXNODE = 10000 ; const int MAXN = 100 ; const int MAXR = 100 ; const int MAXC = 100 ; struct Point { int x , y ; } p[MAXN] ; int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE] ; int H[MAXR] , S[MAXC] ; int col[MAXNODE] ; int size ; int n , K ; LL d[MAXN][MAXN] ; LL a[3000] ; bool vis[MAXN] ; int cnt ; void clear ( int n ) { For ( i , 0 , n ) { L[i] = i - 1 ; R[i] = i + 1 ; U[i] = D[i] = i ; S[i] = 0 ; } clr ( H , -1 ) ; L[0] = n ; R[n] = 0 ; size = n ; } void link ( int r , int c ) { ++ size ; S[c] ++ ; col[size] = c ; U[size] = U[c] ; D[size] = c ; D[U[c]] = size ; U[c] = size ; if ( H[r] != -1 ) { L[size] = L[H[r]] ; R[size] = H[r] ; L[R[size]] = size ; R[L[size]] = size ; } else H[r] = L[size] = R[size] = size ; } void remove ( int c ) { rec ( i , D , c ) { L[R[i]] = L[i] ; R[L[i]] = R[i] ; } } void resume ( int c ) { rec ( i , U , c ) { L[R[i]] = R[L[i]] = i ; } } int h () { int cnt = 0 ; clr ( vis , 0 ) ; rec ( i , R , 0 ) if ( !vis[i] ) { ++ cnt ; vis[i] = 1 ; rec ( j , D , i ) rec ( k , R , j ) vis[col[k]] = 1 ; } return cnt ; } int dance ( int d = 0 ) { if ( d + h () > K ) return 0 ; if ( !R[0] ) return 1 ; int c = R[0] ; rec ( i , R , 0 ) if ( S[c] > S[i] ) c = i ; rec ( i , D , c ) { remove ( i ) ; rec ( j , R , i ) remove ( j ) ; if ( dance ( d + 1 ) ) return 1 ; rec ( j , L , i ) resume ( j ) ; resume ( i ) ; } return 0 ; } void make_map ( LL dist ) { clear ( n ) ; rep ( i , 0 , n ) { link ( i + 1 , i + 1 ) ; rep ( j , i + 1 , n ) { if ( d[i][j] <= dist ) { link ( i + 1 , j + 1 ) ; link ( j + 1 , i + 1 ) ; } } } } int unique ( int n ) { int cnt = 1 ; std :: sort ( a + 1 , a + n + 1 ) ; For ( i , 2 , n ) if ( a[cnt] != a[i] ) a[++ cnt] = a[i] ; return cnt ; } void solve () { scanf ( "%d%d" , &n , &K ) ; rep ( i , 0 , n ) scanf ( "%d%d" , &p[i].x , &p[i].y ) ; cnt = 0 ; rep ( i , 0 , n ) rep ( j , i + 1 , n ) d[j][i] = d[i][j] = ( LL ) abs ( p[i].x - p[j].x ) + ( LL ) abs ( p[i].y - p[j].y ) ; rep ( i , 0 , n ) rep ( j , i + 1 , n ) a[++ cnt] = d[i][j] ; a[++ cnt] = 0 ; cnt = unique ( cnt ) ; int l = 1 , r = cnt ; LL ans = 0 ; while ( l < r ) { int m = ( l + r ) >> 1 ; make_map ( a[m] ) ; if ( dance () ) r = m ; else l = m + 1 ; } printf ( "%I64d\n" , a[l] ) ; } int main () { int T , cas = 0 ; scanf ( "%d", &T ) ; while ( T -- ) { printf ( "Case #%d: " , ++ cas ) ; solve () ; } return 0 ; }