• Solution 「NOI 2017」「洛谷 P3825」游戏


    \(\mathscr{Description}\)

      Link.

      给大家看个乐子: link, 懒得概括题意啦.

    \(\mathscr{Solution}\)

      对于没有 X 的情况, 显然可以 2-SAT; 对于有 X 的情况, 暴力枚举这辆车属于 \(\{X,A\}\) 还是 \(\{B,C\}\), 继续 2-SAT. 复杂度 \(\mathcal O(2^d(n+m))\).

    \(\mathscr{Code}\)

    /* Clearink */
    
    #include <cstdio>
    #include <cstdlib>
    
    const int MAXN = 5e4, MAXM = 1e5;
    int n, cx, m, xpos[10], xid[MAXN + 5];
    char s[MAXN + 5];
    
    inline void chkmin ( int& a, const int b ) { b < a && ( a = b, 0 ); }
    
    inline int id ( const int sta, const int i, const int c ) {
    	if ( ~xid[i] ) {
    		if ( ( sta >> xid[i] ) & 1 ) return c ? -1 : 0;
    		if ( !c ) return -1;
    		return ( c + 2 ) % 3;
    	} else {
    		if ( s[i] == c ) return -1;
    		return ( c - s[i] + 2 ) % 3;
    	}
    }
    
    struct Restrict {
    	int u, a, v, b; // u use a -> v use b.
    	inline void read () {
    		char ta, tb;
    		scanf ( "%d %c %d %c", &u, &ta, &v, &tb ), a = ta - 'A', b = tb - 'A';
    	}
    } restr[MAXM + 5];
    
    struct TwoSAT {
    	static const int MAXND = MAXN << 1, MAXEG = MAXM << 1;
    	int ecnt, head[MAXND + 5], to[MAXEG + 5], nxt[MAXEG + 5];
    	int dfc, dfn[MAXND + 5], low[MAXND + 5], top, stk[MAXND + 5];
    	int scc, clr[MAXND + 5];
    	bool ins[MAXND + 5];
    
    	inline void clear () {
    		ecnt = scc = dfc = 0;
    		for ( int i = 1; i <= n << 1; ++i ) head[i] = dfn[i] = 0;
    	}
    
    	inline void link ( const int s, const int t ) {
    		to[++ecnt] = t, nxt[ecnt] = head[s];
    		head[s] = ecnt;
    	}
    
    	inline void Tarjan ( const int u ) {
    		int v;
    		dfn[u] = low[u] = ++dfc, ins[stk[++top] = u] = true;
    		for ( int i = head[u]; i; i = nxt[i] ) {
    			if ( !dfn[v = to[i]] ) Tarjan ( v ), chkmin ( low[u], low[v] );
    			else if ( ins[v] ) chkmin ( low[u], dfn[v] );
    		}
    		if ( dfn[u] == low[u] ) {
    			++scc;
    			do ins[v = stk[top--]] = false, clr[v] = scc; while ( u ^ v );
    		}
    	}
    
    	inline bool check ( const int sta ) {
    		for ( int i = 1; i <= n << 1; ++i ) if ( !dfn[i] ) Tarjan ( i );
    		for ( int i = 1; i <= n; ++i ) if ( clr[i] == clr[i + n] ) return false;
    		for ( int i = 1; i <= n; ++i ) {
    			bool val = clr[i] > clr[i + n];
    			if ( !~xid[i] ) putchar ( ( s[i] + 1 + val ) % 3 + 'A' );
    			else if ( !( ( sta >> xid[i] ) & 1 ) ) putchar ( 1 + val + 'A' );
    			else putchar ( 'A' );
    		}
    		return putchar ( '\n' ), exit ( 0 ), true;
    	}
    
    	inline void build ( const int sta ) {
    		clear ();
    		for ( int i = 0; i < cx; ++i ) {
    			if ( ( sta >> i ) & 1 ) {
    				link ( xpos[i] + n, xpos[i] ); // choose A only.
    			}
    		}
    		for ( int i = 1; i <= m; ++i ) {
    			int ia = id ( sta, restr[i].u, restr[i].a );
    			int ib = id ( sta, restr[i].v, restr[i].b );
    			if ( !~ia ) continue;
    			if ( !~ib ) link ( restr[i].u + ia * n, restr[i].u + ( ia ^ 1 ) * n );
    			else {
    				link ( restr[i].u + ia * n, restr[i].v + ib * n );
    				link ( restr[i].v + ( ib ^ 1 ) * n, restr[i].u + ( ia ^ 1 ) * n );
    			}
    		}
    	}
    } sat;
    
    int main () {
    	scanf ( "%d %d %s", &n, &cx, s + 1 );
    	for ( int i = 1, t = 0; i <= n; ++i ) {
    		if ( s[i] == 'x' ) {
    			xpos[xid[i] = t++] = i;
    			s[i] = '$';
    		} else s[i] -= 'a', xid[i] = -1;
    	}
    	scanf ( "%d", &m );
    	for ( int i = 1; i <= m; ++i ) restr[i].read ();
    	for ( int s = 0; s < 1 << cx; ++s ) {
    		sat.build ( s );
    		if ( sat.check ( s ) ) return 0;
    	}
    	puts ( "-1" );
    	return 0;
    }
    
    
  • 相关阅读:
    redis教程(三)-----redis缓存雪崩、缓存穿透、缓存预热
    dubbo入门学习(三)-----dubbo整合springboot
    dubbo入门学习(二)-----dubbo hello world
    spring cloud深入学习(十二)-----Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式
    spring cloud深入学习(十三)-----使用Spring Cloud Sleuth和Zipkin进行分布式链路跟踪
    C#关键字params
    C#的lock关键字
    C#的yield关键字
    C#关键字ref和out
    C#的初始化器
  • 原文地址:https://www.cnblogs.com/rainybunny/p/16585700.html
Copyright © 2020-2023  润新知