【UVA11294】Wedding (2-SAT)

题意:

  有N-1对夫妻参加一个婚宴,所有人都坐在一个长长的餐桌左侧或者右侧,新郎和新娘面做面坐在桌子的两侧。由于新娘的头饰很复杂,她无法看到和她坐在同一侧餐桌的人,只能看到对面餐桌的人。任意一对夫妻不能坐在桌子的同侧,另外有m对人吵过架,而新娘不希望看到两个吵过架的人坐在他的对面,问如何安排这些座位。

分析:

  考虑新娘对面那一边,吵过架的不能坐在一起。两夫妻中只能选一个而且必须选一个坐在新娘对面,但不能选两个吵过架的人。所以我们可以用人物关系建图,然后用2-SAT求解。

  另外,说一下2-SAT的不回溯算法,是在图对称的时候才保证正确性的。所以记得保证图是对称的哦。

代码如下:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 #define Maxn 2010
 8 #define Maxm 1000010
 9 
10 int n,m;
11 int first[Maxn];
12 bool mark[Maxn];
13 int s[Maxn],sl;
14 
15 struct node
16 {
17     int x,y,next;
18 }t[Maxm];int len;
19 
20 void ins(int x,int y)
21 {
22     t[++len].x=x;t[len].y=y;
23     t[len].next=first[x];first[x]=len;
24 }
25 
26 bool dfs(int x)
27 {
28     if(mark[x^1]) return 0;
29     if(mark[x]) return 1;
30     mark[x]=1;
31     s[++sl]=x;
32     for(int i=first[x];i;i=t[i].next)
33     {
34         if(!dfs(t[i].y)) return 0;
35     }
36     return 1;
37 }
38 
39 bool ffind()
40 {
41     memset(mark,0,sizeof(mark));
42     mark[0]=1;
43     if(!dfs(0)) return 0;
44     for(int i=1;i<n;i++)
45     {
46         if(mark[i*2]||mark[i*2+1]) continue;
47         sl=0;
48         if(!dfs(i*2))
49         {
50             while(sl) mark[s[sl--]]=0;
51             if(!dfs(i*2+1)) return 0;
52         }
53     }
54     return 1;
55 }
56 
57 int main()
58 {
59     while(1)
60     {
61         scanf("%d%d",&n,&m);
62         if(n==0&&m==0) break;
63         getchar();len=0;
64         memset(first,0,sizeof(first));
65         bool p;
66         for(int i=1;i<=m;i++)
67         {
68             int x,y,p1,p2;
69             char c;
70             scanf("%d%c",&x,&c);getchar();
71             p1=(c=='h'?0:1);
72             scanf("%d%c",&y,&c);//getchar();
73             p2=(c=='h'?0:1);
74             getchar();
75             if(p1==0&&p2==0) p=1;
76             ins(x*2+p1,y*2+1-p2);//ins(y*2+1-p2,x*2+p1);
77             ins(y*2+p2,x*2+1-p1);//ins(x*2+1-p1,y*2+p2);
78         }
79         if(!ffind()) printf("bad luck
");
80         else
81         {
82             for(int i=1;i<n;i++)
83             {
84                 if(i!=1) printf(" ");
85                 if(mark[i*2]) printf("%dw",i);
86                 else printf("%dh",i);
87             }
88         }printf("
");
89     }
90     return 0;
91 }
[uva11294]

2016-03-24 13:24:20

原文地址:https://www.cnblogs.com/Konjakmoyu/p/5315122.html