[BZOJ1823]-[JSOI2010]满汉全席-2-SAT

版权声明:转载嘛....也不是不可以(故作沉思),记得带上me的ID啊qwq https://blog.csdn.net/Izumi_Hanako/article/details/79107080

说在前面

把所有的int都换成了short妄图缩小空间,然而并没有什么用…
好奇那些空间消耗才几十KB是怎么办到的…me的A+B都820KB….
什么时候一定要把 时空优化 好好学一学,嗯!


题目

BZOJ1823传送门

题目大意

这里就直接把问题精炼出来了(原题一堆废话)
给出N个初始元素,每个元素都有两种用法(假设两种用法分别是h和m)。现在有M个限制,形如「第一种元素必须以h的方式使用,第三种元素必须以m的方式使用」,如果不能满足所有的限制,那你将丢失1块钱(可不要小看这1块钱,它可是能买两根棒棒糖!)。询问存不存在一种方案,使你没有损失

输入输出格式

输入格式:
第一行一个整数T,表示数据组数(不超过50)
对于每组数据:
第一行两个整数N,M,含义如题(N不超过100,M不超过1000)
接下来M行,每行以形如「h1 m3」的方式给出限制

输出格式:
对于每组数据,如果存在方案,输出GOOD,否则输出BAD


解法

2-SAT简单题,YY一下就可以做出来
就拿「h1 m3」举例子:
如果已经选了 h3,那么只能选h1;如果已经选了m1,那么只能选m3。于是连边 h3->h1 ,m1->m3
对于其他情况讨论一下即可


下面是自带大长度的代码

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

short T , N , M , oppo[205] , tp , head[205] ;
struct Path{
    short pre , to ;
}p[2*1000+5] ;

template <typename T>
T min( T x , T y ){
    return x < y ? x : y ;
}

char getcha(){
    char rt = getchar() ;
    while( rt < 'a' || rt > 'z' ) rt = getchar() ;
    return rt ;
}

void In( short t1 , short t2 ){
    p[++tp].pre = head[t1] ;
    p[ head[t1] = tp ].to = t2 ;
}

short sta[205] , topp ;
short dfn[205] , dfs_c , scc[205] , scc_cnt ;
short dfs( int u ){
    sta[++topp] = u ;
    short lowu = dfn[u] = ++dfs_c ;
    for( short i = head[u] ; i ; i = p[i].pre ){
        short v = p[i].to ;
        if( !dfn[v] ) lowu = min( lowu , dfs( v ) ) ;
        else if( !scc[v] ) lowu = min( lowu , dfn[v] ) ;
    }
    if( dfn[u] == lowu ){
        scc_cnt ++ ;
        while( 1 ){
            int x = sta[topp--] ;
            scc[x] = scc_cnt ;
            if( x == u ) break ;
        }
    } return lowu ;
}

void solve(){
    for( short i = 1 ; i <= ( N<<1 ) ; i ++ )
        if( !dfn[i] ) dfs( i ) ;
    for( short i = 1 ; i <= N ; i ++ ){
        if( scc[i] == scc[ oppo[i] ] ){ puts( "BAD" ) ; return ; }
    } puts( "GOOD" ) ;
}

void clear(){
    tp = dfs_c = scc_cnt = 0 ;
    memset( head , 0 , sizeof( head ) ) ;
    memset( dfn , 0 , sizeof( dfn ) ) ;
    memset( scc , 0 , sizeof( scc ) ) ;
}

int main(){
    scanf( "%hd" , &T ) ;
    char c1 , c2 ;
    while( T -- ){
        clear() ;
        scanf( "%hd%hd" , &N , &M ) ;
        for( short i = 1 ; i <= N ; i ++ )
            oppo[i] = i + N , oppo[i+N] = i ;
        for( short i = 1 , id1 , id2 ; i <= M ; i ++ ){
            c1 = getcha() ; scanf( "%hd" , &id1 ) ;
            c2 = getcha() ; scanf( "%hd" , &id2 ) ;
            // h is origin, and m is opposite
                   if( c1 == 'h' && c2 == 'm' ){
                In( id2 , id1 ) , In( oppo[id1] , oppo[id2] ) ;
            } else if( c1 == 'h' && c2 == 'h' ){
                In( oppo[id1] , id2 ) , In( oppo[id2] , id1 ) ;
            } else if( c1 == 'm' && c2 == 'h' ){
                In( id1 , id2 ) , In( oppo[id2] , oppo[id1] ) ;
            } else
                In( id1 , oppo[id2] ) , In( id2 , oppo[id1] ) ;
        }
        solve() ;
    }
}
阅读更多
换一批

没有更多推荐了,返回首页