HDU3062 2-sat
2-sat
初次接触2-sat。
首先对于2-sat问题,可简化为:现在有N个党派,每个党派只有2名人员,从2者挑出一个,且某两个党派挑出来的人可能存在矛盾,这时不能同时选择他们。(引用对称性解决2-sat的ppt)
例如:(x1,x2),(y1,y2)为两个不同党派的人。
若两两之间都没有矛盾,则do nothing
若 x1-y1有矛盾,则他们不能同时被选择,所以 (x1,y2)是必选的,或者(x2,y1)是必选的。
然后根据这条规律,tarjan+缩点,得到新的一张图,这张图没有环,若某个“点”中存在(x1,x2)(即:某个党派2个人同时出现在这个“点”中),这是就不能达到目标。
反之成立。
View Code
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<stack> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 2005; 8 const int maxm = maxn*maxn; 9 struct node{ 10 int u,next; 11 }edge[ maxm ]; 12 int head[ maxn ],cnt; 13 int vis[ maxn ],dfn[ maxn ],low[ maxn ],belong[ maxn ],id,cnt2; 14 stack<int>s; 15 void init(){ 16 memset( head,-1,sizeof( head )); 17 cnt=0; 18 id=0; 19 while( !s.empty() ) s.pop(); 20 cnt2=0; 21 memset( vis,0,sizeof( vis )); 22 memset( dfn,-1,sizeof( dfn )); 23 memset( low,-1,sizeof( low )); 24 memset( belong,-1,sizeof( belong )); 25 } 26 void addedge( int a,int b ){ 27 edge[ cnt ].u=b; 28 edge[ cnt ].next=head[ a ]; 29 head[ a ]=cnt++; 30 } 31 32 void tarjan( int now ){ 33 dfn[ now ]=low[ now ]=id++; 34 vis[ now ]=1; 35 s.push( now ); 36 for( int i=head[ now ];i!=-1;i=edge[ i ].next ){ 37 int next=edge[ i ].u; 38 if( dfn[ next ]==-1 ){ 39 tarjan( next ); 40 low[ now ]=min( low[ now ],low[ next ] ); 41 } 42 else if( vis[ next ]==1 ){ 43 low[ now ]=min( low[ now ],dfn[ next ] ); 44 } 45 } 46 if( low[ now ]==dfn[ now ] ){ 47 cnt2++; 48 while( 1 ){ 49 int tmp; 50 tmp=s.top(),s.pop(); 51 vis[ tmp ]=0; 52 belong[ tmp ]=cnt2; 53 if( tmp==now ) break; 54 } 55 } 56 } 57 int main(){ 58 int n,m; 59 while( scanf("%d%d",&n,&m)==2 ){ 60 init(); 61 int a,b,c,d; 62 while( m-- ){ 63 scanf("%d%d%d%d",&a,&b,&c,&d); 64 addedge( 2*a+c,2*b+1-d ); 65 addedge( 2*b+d,2*a+1-c ); 66 } 67 for( int i=0;i<2*n;i++ ) 68 if( dfn[ i ]==-1 ) 69 tarjan( i ); 70 bool flag=true; 71 for( int i=0;i<n;i++ ){ 72 if( belong[ 2*i ]==belong[ 2*i+1 ] ) 73 { 74 flag=false; 75 break; 76 } 77 } 78 puts(flag?"YES":"NO"); 79 //if( flag==1 ) printf("NO\n"); 80 //else printf("YES\n"); 81 } 82 return 0; 83 }
keep moving...