Loading

所驼门王的宝藏

一眼就是\(tarjan\)缩点+\(dag\)\(dp\).
原题数据并没有什么难点,直接暴力\(vector,map\)建边就\(A\)了。
但本质上这只是对没有宝藏的点的一种优化,如果某列或者某行全是宝藏,这个优化没有一点用。
然后数据加强了。。。。
我们需要一个技巧,可以让上限时空复杂度都降下来。
对每一行,每一列建一个虚点,虚点连向这一行,列上的所有宝藏。
如果一个点是横天门,纵,,门,就让这个点向虚点建边,进而达到了向该列所有点建边的效果。
注意统计答案的时候不要统计虚点。

code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#define int long 
#define R register int
#define printf Ruusupuu = printf
#define mp( x , y ) make_pair( x , y ) 

using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
const int N = 3e5 + 10 ;

int Ruusupuu ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
	while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
	return fg ? -w : w ;
}

int n , ms , ks , cnt , cnts , tnt , gnt , head [N] , heads [N] , h [N] , l [N] , kk ;
int dfn [N] , low [N] , st [N] , kin [N] , top , dr [N] , f [N] , w [N] ; bool fg [N] ;
struct P{ int x , y , opt ; } a [N] ; 
map< pair< int , int > , vector< int > > m ;
map< pair< int , int > , bool > hs ;
struct E{ int fr , to , next ; } e [N << 2] , es [N] ;

inline void add( int f , int t ){
	e [++ cnt].fr = f ;
	e [cnt].to = t ;
	e [cnt].next = head [f] ;
	head [f] = cnt ;
}

inline void adds( int f , int t ){
	es [++ cnts].fr = f ;
	es [cnts].to = t ;
	es [cnts].next = heads [f] ;
	heads [f] = cnts ;
}

void sc(){
	n = read() , ms = read() , ks = read() ; kk = n ;
	memset( head , -1 , sizeof( head ) ) ;
	memset( heads , -1 , sizeof( heads ) ) ; 
	for( R i = 1 ; i <= n ; i ++ ){
		a [i].x = read() , a [i].y = read() , a [i].opt = read() ;
		if( !h [a [i].x] ) h [a [i].x] = ++ kk ;
		if( !l [a [i].y] ) l [a [i].y] = ++ kk ;
		add( h [a [i].x] , i ) ;
		add( l [a [i].y] , i ) ;
		m [mp( a [i].x + 1 , a [i].y + 1 )].push_back( i ) ;
		m [mp( a [i].x + 1 , a [i].y )].push_back( i ) ;
		m [mp( a [i].x , a [i].y + 1 )].push_back( i ) ;
		m [mp( a [i].x - 1 , a [i].y - 1 )].push_back( i ) ;
		m [mp( a [i].x , a [i].y - 1 )].push_back( i ) ;
		m [mp( a [i].x - 1 , a [i].y )].push_back( i ) ;
		m [mp( a [i].x + 1 , a [i].y - 1 )].push_back( i ) ;
		m [mp( a [i].x - 1 , a [i].y + 1 )].push_back( i ) ;
	}
	
	for( R i = 1 ; i <= n ; i ++ ){
		if( a [i].opt == 1 ) add( i , h [a [i].x] ) ;
		if( a [i].opt == 2 ) add( i , l [a [i].y] ) ;
		if( a [i].opt == 3 ){
			pair< int , int > p = mp( a [i].x , a [i].y ) ;
			for( R j = 0 ; j < m [p].size() ; j ++ )
				if( i != m [p][j] ) add( i , m [p][j] ) ;
		}
	}
	
//	for( R i = 1 ; i <= n ; i ++ ) for( R j = head [i] ; ~j ; j = e [j].next ) printf( "%ld %ld\n" , i , e [j].to ) ;
}

inline void tj( int x ){
	dfn [x] = low [x] = ++ tnt ;
	st [++ top] = x ; fg [x] = 1 ;
	for( R i = head [x] ; ~i ; i = e [i].next ){
		int y = e [i].to ;
		if( !dfn [y] )
			tj( y ) , low [x] = min( low [x] , low [y] ) ;
		else if( fg [y] )
			low [x] = min( low [x] , dfn [y] ) ;
	}
	
	if( dfn [x] == low [x] ){
		int tmp ; gnt ++ ;
		do{
			tmp = st [top --] ;
			fg [tmp] = 0 ;
			kin [tmp] = gnt ;
			if( tmp <= n ) w [gnt] ++ ;
		}while( x != tmp ) ;
	}

}

inline void topsort(){
	queue< int > q ;  memset( f , -0x3f , sizeof( f ) ) ;
	for( R i = 1 ; i <= gnt ; i ++ ) if( !dr [i] ) {
		f [i] = w [i] , q.push( i ) ; 
	}// printf( "%ld\n" , f [i] ) ;
	while( !q.empty() ){
		int t = q.front() ; q.pop() ;
		for( R i = heads [t] ; ~i ; i = es [i].next ){
			int y = es [i].to ; 
			f [y] = max( f [y] , f [t] + w [y] ) ;
		//	printf( "RE%ld %ld\n" , y , f [y] ) ;
			dr [y] -- ; if( dr [y] == 0 ) q.push( y ) ;
		}
	}
	int ans = 0 ; 
	for( R i = 1 ; i <= n ; i ++ )
		ans = max( ans , f [i] ) ;
	printf( "%ld\n" , ans ) ;
}

void work(){
	
	for( R i = 1 ; i <= n ; i ++ ) if( !dfn [i] ) tj( i ) ; 
	for( R i = 1 ; i <= kk ; i ++ ){
		for( R j = head [i] ; ~j ; j = e [j].next ){
			int y = e [j].to ; if( !kin [i] || !kin [y] ) continue ;
			if( kin [y] != kin [i] && !hs[mp( kin [i] , kin [y] )] )
				adds( kin [i] , kin [y] ) , dr [kin [y]] ++ , hs [mp( kin [i] , kin [y] )] = 1 ; 
		}
	}
	
//	for( R i = 1 ; i <= n ; i ++ ) 
//		printf( "BL%ld\n" , kin [i] ) ;	
/*	for( R i = 1 ; i <= n ; i ++ ) 
		for( R j = heads [i] ; ~j ; j = es [j].next )
			printf( "%ld %ld\n" , i , es [j].to ) ;*/
			
	topsort() ;

}

signed main(){	
	sc() ;
	work() ;
	return 0 ;
}
posted @ 2021-06-09 08:07  Soresen  阅读(54)  评论(0)    收藏  举报