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 }

 

你可能感兴趣的:(HDU)