POJ 3683 Priest John's Busiest Day

本文详细解析了2-SAT算法的应用实例,通过婚礼现场时间安排问题来阐述算法原理及实现细节,强调避免使用邻接链表以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一道裸的2-Sat,只要考虑矛盾条件的判断就好了。

矛盾判断:

对于婚礼现场 x 和 y,x 的第一段可以和 y 的第一段或者第二段矛盾,同理,x 的第二段可以和 y 的第一段或者第二段矛盾,条件是 x 的 1或2 段与 y 的 1或2 段有重合,那么选了 x 某一段就不能选择其矛盾的那一段,那就只能选择 y 中的另一段,建立一条 x (u)-> y ( v的对立 ),同理,x (u的对立)<- y ( v ) 。

代码是:

for ( int  i = 1 ; i <= n ; i ++ ) 
			for ( int  j = 1 ; j <= n ; j ++ ) 
				if ( i != j ) {
					if ( conflict ( i , j ) ) {
						create ( i , j + n ) ;
						create ( j , i + n ) ;
					}
					if ( conflict ( i , j + n ) ) {
						create ( i , j ) ;
						create ( j + n , i + n ) ;
					}
					if ( conflict ( i + n , j ) ) {
						create ( i + n , j + n ) ;
						create ( j , i ) ;
					}
					if ( conflict ( i + n , j + n ) ) {
						create ( i + n , j ) ;
						create ( j + n , i ) ;
					}
				}
		

真的,2-sat千万不要用邻接链表!!!卡死卡死卡死!!!稠密图!!!不要用!!!

我WA和RE和MLE都怪邻接链表!!!!!!!!!!!!!!!!!!!!!!!!!

总代码:

下面第一个代码纪念邻接链表这个垃圾的Failure!

#include <cstdio>
#include <stack>
#include <queue>
#include <cstring>

const  int  N = 2000000 + 5 ;

std :: stack < int >  s ;
std :: queue < int >  q ;

struct  ConfirmedHY {
	int  st ;
	int  en ;
}
dot [ N ] ;

int  head [ N ] , nxt [ N ] , to [ N ] , cn ;
int  headx [ N ] , nxtx [ N ] , tox [ N ] , cnn ;
int  dfn [ N ] , low [ N ] , belong [ N ] , cnt , cnx ;
int  ind [ N ] , op [ N ] , color [ N ] ;
int  sth , stm , enh , enm , len , n ;
bool  ins [ N ] ;

int  minx ( int  a , int  b ) {
	return  a > b ? b : a ;
}

void  create ( int  u , int  v ) {
	cn ++ ;
	to [ cn ] = v ;
	nxt [ cn ] = head [ u ] ;
	head [ u ] = cn ;
}

void  create_x ( int  u , int  v ) {
	cnn ++ ;
	tox [ cnn ] = v ;
	nxtx [ cnn ] = headx [ u ] ;
	headx [ u ] = cnn ;
}

bool  conflict ( int  id1 , int  id2 ) {
	int  st1 = dot [ id1 ] . st , en1 = dot [ id1 ] . en ;
	int  st2 = dot [ id2 ] . st , en2 = dot [ id2 ] . en ;
	if ( st1 >= en2  ||  st2 >= en1 )
		return  false ;
	return  true ;
}

void  rebuild ( ) {
	
	for ( int  i = 1 ; i <= 2 * n ; i ++ ) {
		int  tmp1 = belong [ i ] ;
		for ( int  j = head [ i ] ; j ; j = nxt [ j ] ) {
			int  tmp2 = belong [ to [ j ] ] ;
			if ( tmp1 != tmp2 ) {
				create_x ( tmp2 , tmp1 ) ;
				ind [ tmp1 ] ++ ;
			}
		}
	}
	
}

void  opp ( ) {
	for ( int  i = 1 ; i <= n ; i ++ ) {
		op [ belong [ i ] ] = belong [ i + n ] ;
		op [ belong [ i + n ] ] = belong [ i ] ;
	}
}

bool  judge () {
	for ( int  i = 1 ; i <= n ; i ++ )
		if ( belong [ i ] == belong [ i + n ] )
			return  true ;
	return  false ;
}
 
void  topsort ( ) {
	for ( int  i = 1 ; i <= cnx ; i ++ )
	    if ( ind [ i ] == 0 ) 
	    	q . push ( i ) ;
	while ( ! q . empty ( ) ) {
		int  tmp = q . front ( ) ;
		q . pop ( ) ; 
		if ( color [ tmp ] == 0 )
			color [ tmp ] = 1 , color [ op [ tmp ] ] = 2 ;
		//if ( color [ tmp ] == 2 )  continue ;
		for ( int  i = headx [ tmp ] ; i ; i = nxtx [ i ] ) {
			ind [ tox [ i ] ] -- ;
			if ( ! ind [ tox [ i ] ] )
				q . push ( tox [ i ] ) ;
		}
	}
}

void  tarjan ( int  x ) {
	cnt ++ ;
	dfn [ x ] = low [ x ] = cnt ;
	ins [ x ] = true ; s . push ( x ) ;
	for ( int  i = head [ x ] ; i ; i = nxt [ i ] ) {
		int  v = to [ i ] ;
		if ( ! dfn [ v ] ) {
			tarjan ( v ) ;
			low [ x ] = minx ( low [ x ] , low [ v ] ) ;
		}
		else  if  ( ins [ v ] )  low [ x ] = minx ( low [ x ] , dfn [ v ] ) ;
	}
	if ( dfn [ x ] == low [ x ] ) {
		cnx ++ ;
		while ( 1 ) {
			int  tmp = s . top ( ) ;
			s . pop ( ) ;
			ins [ tmp ] = false ;
			belong [ tmp ] = cnx ;
			if ( x == tmp ) break ;
		}
	}
}

int  main ( ) {
	
	while ( scanf ( "%d" , & n ) == 1 ) {
		
		cnx = 0 ; cnt = 0 ; cn = 0 ; cnn = 0 ;
		memset ( head , 0 , sizeof ( head ) ) ;
		memset ( nxt , 0 , sizeof ( nxt ) ) ;
		memset ( to , 0 , sizeof ( to ) ) ;
		memset ( headx , 0 , sizeof ( headx ) ) ;
		memset ( nxtx , 0 , sizeof ( nxtx ) ) ;
		memset ( tox , 0 , sizeof ( tox ) ) ;
		memset ( belong , 0 , sizeof ( belong ) ) ;
		memset ( dfn , 0 , sizeof ( dfn ) ) ;
		memset ( ins , false , sizeof ( ins ) ) ;
		memset ( low , 0 , sizeof ( low ) ) ;
		memset ( dot , 0 , sizeof ( dot ) ) ;
		memset ( ind , 0 , sizeof ( ind ) ) ;
		memset ( op , 0 , sizeof ( op ) ) ;
		memset ( color , 0 , sizeof ( color ) ) ;
		
		for ( int  i = 1 ; i <= n ; i ++ ) {
			scanf ( "%d:%d %d:%d %d" , & sth , & stm , & enh , & enm , & len ) ;
			dot [ i ] . st = sth * 60 + stm ;
			dot [ i ] . en = sth * 60 + stm + len ;
			dot [ i + n ] . st = enh * 60 + enm - len ; 
			dot [ i + n ] . en = enh * 60 + enm ;
		}
		
		for ( int  i = 1 ; i <= n ; i ++ ) 
			for ( int  j = 1 ; j <= n ; j ++ ) 
				if ( i != j ) {
					if ( conflict ( i , j ) ) {
						create ( i , j + n ) ;
						create ( j , i + n ) ;
					}
					if ( conflict ( i , j + n ) ) {
						create ( i , j ) ;
						create ( j + n , i + n ) ;
					}
					if ( conflict ( i + n , j ) ) {
						create ( i + n , j + n ) ;
						create ( j , i ) ;
					}
					if ( conflict ( i + n , j + n ) ) {
						create ( i + n , j ) ;
						create ( j + n , i ) ;
					}
				}
		
		for ( int  i = 1 ; i <= 2 * n ; i ++ ) 
		    if ( ! dfn [ i ] ) 
		    	tarjan ( i ) ;
		
		if ( judge ( ) ) {
			printf ( "NO\n" ) ;
			continue ;
		}
		else  printf ( "YES\n" ) ;
		
		rebuild ( ) ;
		
		opp ( ) ;
		
		topsort ( ) ;
		
		for ( int  i = 1 ; i <= n ; i ++ )
			if ( color [ belong [ i ] ] == 1 )
				printf ( "%.2d:%.2d %.2d:%.2d\n" , dot [ i ] . st / 60 , dot [ i ] . st % 60 , dot [ i ] . en / 60 , dot [ i ] . en % 60 ) ;
			else 
				printf ( "%.2d:%.2d %.2d:%.2d\n" , dot [ i + n ] . st / 60 , dot [ i + n ] . st % 60 , dot [ i + n ] . en / 60 , dot [ i + n ] . en % 60 ) ;
	}
	
	return  0 ;
}

下面是AC代码

#include <cstdio>
#include <stack>
#include <queue>
#include <cstring>

const  int  N = 4000 + 5 ;

std :: stack < int >  s ;
std :: queue < int >  q ;
std :: vector < int >  g [ N ] , rg [ N ] ;

struct  ConfirmedHY {
	int  st ;
	int  en ;
}
dot [ N ] ;

int  dfn [ N ] , low [ N ] , belong [ N ] , cnt , cnx ;
int  ind [ N ] , op [ N ] , color [ N ] ;
int  sth , stm , enh , enm , len , n ;
bool  ins [ N ] ;

int  minx ( int  a , int  b ) {
	return  a > b ? b : a ;
}

void  create ( int  u , int  v ) {
	g [ u ] . push_back ( v ) ;
}

void  create_x ( int  u , int  v ) {
	rg [ u ] . push_back ( v ) ;
}

bool  conflict ( int  id1 , int  id2 ) {
	int  st1 = dot [ id1 ] . st , en1 = dot [ id1 ] . en ;
	int  st2 = dot [ id2 ] . st , en2 = dot [ id2 ] . en ;
	if ( st1 >= en2  ||  st2 >= en1 )
		return  false ;
	return  true ;
}

void  rebuild ( ) {
	
	for ( int  i = 1 ; i <= 2 * n ; i ++ ) {
		int  tmp1 = belong [ i ] ;
		for ( int  j = 0 ; j < g [ i ] . size ( ) ; j ++ ) {
			int  tmp2 = belong [ g [ i ] [ j ] ] ;
			if ( tmp1 != tmp2 ) {
				create_x ( tmp2 , tmp1 ) ;
				ind [ tmp1 ] ++ ;
			}
		}
	}
	
}

void  opp ( ) {
	for ( int  i = 1 ; i <= n ; i ++ ) {
		op [ belong [ i ] ] = belong [ i + n ] ;
		op [ belong [ i + n ] ] = belong [ i ] ;
	}
}

bool  judge () {
	for ( int  i = 1 ; i <= n ; i ++ )
		if ( belong [ i ] == belong [ i + n ] )
			return  true ;
	return  false ;
}
 
void  topsort ( ) {
	for ( int  i = 1 ; i <= cnx ; i ++ )
	    if ( ind [ i ] == 0 ) 
	    	q . push ( i ) ;
	while ( ! q . empty ( ) ) {
		int  tmp = q . front ( ) ;
		q . pop ( ) ; 
		if ( color [ tmp ] == 0 )
			color [ tmp ] = 1 , color [ op [ tmp ] ] = 2 ;
		//if ( color [ tmp ] == 2 )  continue ;
		for ( int  i = 0 ; i < rg [ tmp ] . size ( ) ; i ++ ) {
			int  v = rg [ tmp ] [ i ] ;
			ind [ v ] -- ;
			if ( ! ind [ v ] )
				q . push ( v ) ;
		}
	}
}

void  tarjan ( int  x ) {
	cnt ++ ;
	dfn [ x ] = low [ x ] = cnt ;
	ins [ x ] = true ; s . push ( x ) ;
	for ( int  i = 0 ; i < g [ x ] . size ( ) ; i ++ ) {
		int  v = g [ x ] [ i ] ;
		if ( ! dfn [ v ] ) {
			tarjan ( v ) ;
			low [ x ] = minx ( low [ x ] , low [ v ] ) ;
		}
		else  if  ( ins [ v ] )  low [ x ] = minx ( low [ x ] , dfn [ v ] ) ;
	}
	if ( dfn [ x ] == low [ x ] ) {
		cnx ++ ;
		while ( 1 ) {
			int  tmp = s . top ( ) ;
			s . pop ( ) ;
			ins [ tmp ] = false ;
			belong [ tmp ] = cnx ;
			if ( x == tmp ) break ;
		}
	}
}

int  main ( ) {
	
	while ( scanf ( "%d" , & n ) == 1 ) {
		
		cnx = 0 ; cnt = 0 ;
		memset ( belong , 0 , sizeof ( belong ) ) ;
		memset ( dfn , 0 , sizeof ( dfn ) ) ;
		memset ( ins , false , sizeof ( ins ) ) ;
		memset ( low , 0 , sizeof ( low ) ) ;
		memset ( dot , 0 , sizeof ( dot ) ) ;
		memset ( ind , 0 , sizeof ( ind ) ) ;
		memset ( op , 0 , sizeof ( op ) ) ;
		memset ( color , 0 , sizeof ( color ) ) ;
		
		for ( int  i = 1 ; i <= n ; i ++ ) {
			scanf ( "%d:%d %d:%d %d" , & sth , & stm , & enh , & enm , & len ) ;
			dot [ i ] . st = sth * 60 + stm ;
			dot [ i ] . en = sth * 60 + stm + len ;
			dot [ i + n ] . st = enh * 60 + enm - len ; 
			dot [ i + n ] . en = enh * 60 + enm ;
		}
		
		for ( int  i = 1 ; i <= n ; i ++ ) 
			for ( int  j = 1 ; j <= n ; j ++ ) 
				if ( i != j ) {
					if ( conflict ( i , j ) ) {
						create ( i , j + n ) ;
						create ( j , i + n ) ;
					}
					if ( conflict ( i , j + n ) ) {
						create ( i , j ) ;
						create ( j + n , i + n ) ;
					}
					if ( conflict ( i + n , j ) ) {
						create ( i + n , j + n ) ;
						create ( j , i ) ;
					}
					if ( conflict ( i + n , j + n ) ) {
						create ( i + n , j ) ;
						create ( j + n , i ) ;
					}
				}
		
		for ( int  i = 1 ; i <= 2 * n ; i ++ ) 
		    if ( ! dfn [ i ] ) 
		    	tarjan ( i ) ;
		
		if ( judge ( ) ) {
			printf ( "NO\n" ) ;
			continue ;
		}
		else  printf ( "YES\n" ) ;
		
		rebuild ( ) ;
		
		opp ( ) ;
		
		topsort ( ) ;
		
		for ( int  i = 1 ; i <= n ; i ++ )
			if ( color [ belong [ i ] ] == 1 )
				printf ( "%.2d:%.2d %.2d:%.2d\n" , dot [ i ] . st / 60 , dot [ i ] . st % 60 , dot [ i ] . en / 60 , dot [ i ] . en % 60 ) ;
			else 
				printf ( "%.2d:%.2d %.2d:%.2d\n" , dot [ i + n ] . st / 60 , dot [ i + n ] . st % 60 , dot [ i + n ] . en / 60 , dot [ i + n ] . en % 60 ) ;
		
		for ( int  i = 1 ; i <= 2 * n ; i ++ ) {
			g [ i ] . clear ( ) ;
			rg [ i ] . clear ( ) ;
		} 
	}
	
	return  0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值