zoukankan      html  css  js  c++  java
  • [NOI2017]游戏

    题目

    点这里看题目。

    分析

    注意到,非 x 的赛道只有两种赛车可选,所以如果只有 a,b,c ,那么限制可以转化为 2-SAT 的边。下面我们用 ( eg h_i) 表示在 (i) 号位上不选择 (h_i) 这辆车。我们可以如下转化:

    1. 如果 ((i,h_i,j,h_j)) 中, (h_i) 本身不可选,该限制自然作废。
    2. 如果 ((i,h_i,j,h_j)) 中, (h_j) 本身不可选,那么 (h_i) 也不可选,即 (h_i ightarrow eg h_i)
    3. 如果 ((i,h_i,j,h_j)) 中, 两种车各自都可以选,那么显然连接 (h_i ightarrow h_j)( eg h_j ightarrow eg h_i)

    现在考虑处理 x 。虽然我们不难想到 (O(3^d imes m)) 进行枚举,但是实际上我们只需要考虑 x 上选取 (A,B,C) 的情况。而 a 已经包含了选 (B,C)b 已经包含了选 (A,C) 。如果我们将 x 均替换为 ab ,那么我们已经考虑了所有的情况。因此只需要 (O(2^d imes m)) 便可以。

    小结:

    1. x 替换做 a,b ,利用其含义进行 " 部分枚举 " ,而避免了直接枚举的高复杂度。

    代码

    #include <cstdio>
    
    #define Opp( x ) ( x <= N ? x + N : x - N )
    
    const int MAXN = 1e5 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0; char s = getchar(); int f = 1;
    	while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ) putchar( '-' ), x = -x;
    	if( 9 < x ) write( x / 10 );
    	putchar( x % 10 + '0' );
    }
    
    template<typename _T>
    _T MIN( const _T a, const _T b )
    {
    	return a < b ? a : b;
    }
    
    struct Edge
    {
    	int to, nxt;
    }Graph[MAXN * 10];
    
    struct Ristriction
    {
    	int x, y; char hx, hy;
    	
    	void Read() 
    	{ 
    		scanf( "%d %c %d %c", &x, &hx, &y, &hy );
    		hx += 'a' - 'A', hy += 'a' - 'A';
    	}
    }R[MAXN];
    
    int stk[MAXN], top;
    
    int id[MAXN];
    char S[MAXN], fir[3] = { 'b', 'a', 'a' }, avail[3][2] = { { 'b', 'c' }, { 'a', 'c' }, { 'a', 'b' } };
    int seq[10], xtot;
    
    int head[MAXN], DFN[MAXN], LOW[MAXN], bel[MAXN];
    int N, M, D, cnt, tot, ID;
    bool in[MAXN];
    
    void AddEdge( const int from, const int to )
    {
    	Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
    	head[from] = cnt;
    }
    
    void Tarjan( const int u )
    {
    	DFN[u] = LOW[u] = ++ ID;
    	in[stk[++ top] = u] = true;
    	for( int i = head[u], v ; i ; i = Graph[i].nxt )
    		if( ! DFN[v = Graph[i].to] ) Tarjan( v ), LOW[u] = MIN( LOW[u], LOW[v] );
    		else if( in[v] ) LOW[u] = MIN( LOW[u], DFN[v] );
    	if( DFN[u] == LOW[u] )
    	{
    		int v; tot ++;
    		do in[v = stk[top --]] = false, bel[v] = tot;
    		while( v ^ u );
    	}
    }
    
    void Clean()
    {
    	ID = tot = top = cnt = 0;
    	for( int i = 1 ; i <= N * 2 ; i ++ ) 
    		head[i] = LOW[i] = DFN[i] = bel[i] = 0;
    }
    
    bool Chk()
    {
    	Clean();
    	for( int i = 1 ; i <= N ; i ++ ) id[i] = S[i] - 'a';
    	for( int i = 1 ; i <= M ; i ++ )
    	{
    		if( R[i].hx == S[R[i].x] ) continue;
    		if( R[i].hy == S[R[i].y] ) 
    		{
    			int t = ( R[i].hx == fir[id[R[i].x]] ? R[i].x : Opp( R[i].x ) );
    			AddEdge( t, Opp( t ) );
    		}
    		else 
    		{
    			int u = ( R[i].hx == fir[id[R[i].x]] ? R[i].x : Opp( R[i].x ) ),
    				v = ( R[i].hy == fir[id[R[i].y]] ? R[i].y : Opp( R[i].y ) );
    			AddEdge( u, v ), AddEdge( Opp( v ), Opp( u ) );
    		}
    	}
    	for( int i = 1 ; i <= N * 2 ; i ++ ) if( ! DFN[i] ) Tarjan( i );
    	for( int i = 1 ; i <= N ; i ++ ) if( bel[i] == bel[i + N] ) return false;
    	return true;
    }
    
    int main()
    {
    	bool flg = false;
    	read( N ), read( D );
    	scanf( "%s", S + 1 ), read( M );
    	for( int i = 1 ; i <= M ; i ++ ) R[i].Read();
    	for( int i = 1 ; i <= N ; i ++ ) if( S[i] == 'x' ) seq[++ xtot] = i;
    	for( int s = 0 ; s < ( 1 << xtot ) ; s ++ )
    	{
    		for( int i = 1 ; i <= xtot ; i ++ )
    			S[seq[i]] = 'a' + ( s >> ( i - 1 ) & 1 );
    		if( flg = Chk() ) break;
    	}
    	if( ! flg ) { puts( "-1" ); return 0; }
    	for( int i = 1 ; i <= N ; i ++ )
    		putchar( avail[id[i]][bel[i + N] < bel[i]] - 'a' + 'A' );
    	putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    mysql int类型 int(11) 和int(2)区别
    mysql 用户 登陆 权限相关
    【转】ext4+delalloc造成单次写延迟增加的分析
    write 系统调用耗时长的原因
    【转】通过blktrace, debugfs分析磁盘IO
    win7 wifi热点
    【SystemTap】 Linux下安装使用SystemTap源码安装SystemTap
    pdflush进程介绍与优化【转】
    How to find per-process I/O statistics on Linux
    oom_killer
  • 原文地址:https://www.cnblogs.com/crashed/p/14116214.html
Copyright © 2011-2022 走看看