• UVa 11294


    题目:有一场婚礼,有n对夫妇參加。他们之间有些人之间有奸情(可能同性),在场的人中有一个公主。 

                她清楚其它人的人际关系,问是否能安排座位使得两边都是n个人,且公主看不见有奸情的人同一时候在的对面。

    分析:2-SAT。直接依照看的流程敲的程序。

                1.建图,矛盾的点建立相应的边(与一直关系相反)。

                2.利用Tarjan算法计算强连通分量,缩点;

                3.推断是否有解(是否有夫妇在同一集合);

                4.假设成立,利用拓扑排序求出一组解。输出。

    说明:第一个2SAT(⊙_⊙)。

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    //link_list_begin
    typedef struct enode
    {
    	int 	point;
    	enode* 	next;
    }edge;
    edge*H1[204],*H2[204];
    edge E1[40004],E2[40004];
    int  e_size1,e_size2;
    
    void link_init( void )
    {
    	e_size1 = 0; e_size2 = 0;
    	memset( H1, 0, sizeof(H1) );
    	memset( H2, 0, sizeof(H2) );
    	memset( E1, 0, sizeof(E1) );
    	memset( E2, 0, sizeof(E2) );
    }
    
    void link_add1( int a, int b )
    {
    	E1[e_size1].point = b;
    	E1[e_size1].next = H1[a];
    	H1[a] = &E1[e_size1 ++];
    }
    
    void link_add2( int a, int b )
    {
    	E2[e_size2].point = b;
    	E2[e_size2].next = H2[a];
    	H2[a] = &E2[e_size2 ++];
    }
    //link_list_end
    
    int  s_id,times,top;
    int  dfn[204],low[204],use[204],stk[204],oth[204],set[204];
    void tarjan( int i, int j ) 
    {
    	dfn[i] = low[i] = ++ times;
    	use[i] = 1;
    	stk[++ top] = i;
    	for ( edge* p = H1[i] ; p ; p = p->next ) {
    		if ( !dfn[p->point] ) {
    			tarjan(p->point, 0);
    			low[i] = min(low[i], low[p->point]);
    		}else if ( use[p->point] ) 
    			low[i] = min(low[i], dfn[p->point]);
    	}
    	if ( dfn[i] == low[i] ) {
    		s_id ++;
    		do {
    			j = stk[top --];
    			use[j] = 0;
    			set[j] = s_id;
    		}while ( j != i );
    	}
    }
    
    void dfs( int i )
    {
    	for ( edge* p = H2[i] ; p ; p = p->next ) 
    		if ( !use[p->point] ) {
    			dfs(p->point);
    			use[i] = use[p->point];
    			use[oth[i]] = use[oth[p->point]];
    		}
    	use[i] = 1;
    	use[oth[i]] = 2;
    }
    
    void solve( int n )
    {
    	//强连通分量 
    	s_id = times = top = 0;
    	memset( dfn, 0, sizeof(dfn) );
    	memset( use, 0, sizeof(use) );
    	for ( int i = 0 ; i < 2*n ; ++ i )
    		if ( !dfn[i] )
    			tarjan(i, 0);
    	
    	//无解推断 
    	for ( int i = 0 ; i < n ; ++ i )
    		if ( set[i*2] == set[i*2+1] ) {
    			printf("bad luck
    ");
    			return;
    		}else {
    			oth[set[i*2]] = set[i*2+1];
    			oth[set[i*2+1]] = set[i*2];
    		}
    		
    	//拓扑排序 
    	times = 0;
    	memset( use, 0, sizeof(use) );
    	for ( int i = 0 ; i < 2*n ; ++ i )
    		for ( edge* p = H1[i] ; p ; p = p->next )
    			if ( set[p->point] != set[i] )
    				link_add2( set[i], set[p->point] );
    	for ( int i = 1 ; i <= s_id ; ++ i )
    		if ( !use[i] )
    			 dfs(i);
    
    	for ( int i = 1 ; i < n ; ++ i ) {
    		if ( i > 1 ) printf(" ");
    		if ( use[set[i*2]] == use[set[0]] )
    			printf("%dw",i);
    		else printf("%dh",i);
    	}
    	printf("
    ");
    }
    
    int main()
    {
    	int  n,m,x,y;
    	char ch1,ch2;
    	while ( ~scanf("%d%d",&n,&m) && n ) {
    		
    		link_init();
    		link_add1( 0, 1 );
    		for ( int i = 0 ; i < m ; ++ i ) {
    			scanf("%d%c %d%c",&x,&ch1,&y,&ch2);	
    					
    			x <<= 1; y <<= 1;
    			if ( ch1 == 'w' ) x ^= 1;
    			if ( ch2 == 'w' ) y ^= 1;
    			link_add1( x^1, y );
    			link_add1( y^1, x );
    		}
    		
    		solve( n );
    	}
    	return 0;
    }
    

  • 相关阅读:
    Mybatis-plugin插件的使用
    SpringBoot整合mybatis-pagehelper实现分页
    springboot打war包
    keepalived1.4.0安装启动卸载
    六、nginx 搭建高可用集群
    五、nginx的动静分离
    四、nginx的负载均衡
    linux中mysql忘记root密码如何登陆
    十分钟到你了解OpenStack--nova组件
    docker 中 add 和 copy 的区别
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7029276.html
Copyright © 2020-2023  润新知