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 }

 

posted @ 2013-02-04 15:20  xxx0624  阅读(524)  评论(0编辑  收藏  举报