Poj--3648(2-SAT,拓扑排序)
2014-10-20 16:09:58
思路:2-SAT好题。0,2,4...表示husband,1,3,5...表示wife 。我把任务定义为选择坐在新娘对面的人。
限制条件:(1)有暧昧关系的一对不能同时坐在新娘对面,所以根据每一对(i,j),连边 i->j' , j -> i'这两条必须边。
(2)一对夫妻不能坐在同一边
(3)新娘新郎不在同边,所以连边 1->0(显然新娘不能坐在新娘对面)
(4)拓扑排序要反向建边
1 /************************************************************************* 2 > File Name: 3648.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 19 Oct 2014 02:28:34 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 1000; 27 28 int n,m; 29 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 30 int f1[maxn],n1[maxn * maxn],v1[maxn * maxn],e1; 31 int low[maxn],dfn[maxn],sc[maxn],scnt,tot; 32 int din[maxn],col[maxn],asc[maxn]; 33 queue<int> Q; 34 stack<int> S; 35 36 void Add_edge(int u,int v){ 37 next[++ecnt] = first[u]; 38 ver[ecnt] = v; 39 first[u] = ecnt; 40 } 41 42 void Init(){ 43 memset(din,0,sizeof(din)); 44 memset(first,-1,sizeof(first)); 45 memset(f1,-1,sizeof(f1)); 46 memset(asc,0,sizeof(asc)); 47 ecnt = 0; 48 e1 = 0; 49 } 50 51 void Dfs(int p){ 52 dfn[p] = low[p] = ++tot; 53 S.push(p); 54 for(int i = first[p]; i != -1; i = next[i]){ 55 int v = ver[i]; 56 if(!dfn[v]){ 57 Dfs(v); 58 low[p] = min(low[p],low[v]); 59 } 60 else if(!sc[v]){ 61 low[p] = min(low[p],dfn[v]); 62 } 63 } 64 if(low[p] == dfn[p]){ 65 ++scnt; 66 while(1){ 67 int x = S.top(); 68 S.pop(); 69 sc[x] = scnt; 70 if(x == p) break; 71 } 72 } 73 } 74 75 void Tarjan(){ 76 memset(dfn,0,sizeof(dfn)); 77 memset(low,0,sizeof(low)); 78 memset(sc,0,sizeof(sc)); 79 while(!S.empty()) S.pop(); 80 scnt = tot = 0; 81 for(int i = 0; i < 2 * n; ++i) 82 if(!dfn[i]) Dfs(i); 83 } 84 85 void Add_edge1(int u,int v){ 86 n1[++e1] = f1[u]; 87 v1[e1] = v; 88 f1[u] = e1; 89 } 90 91 void Build_dag(){ 92 for(int i = 0; i < 2 * n; ++i){ 93 for(int j = first[i]; j != -1; j = next[j]){ 94 int v = ver[j]; 95 if(sc[i] != sc[v]){ 96 Add_edge1(sc[v],sc[i]); 97 din[sc[i]]++; 98 } 99 } 100 } 101 } 102 103 void Toposort(){ 104 while(!Q.empty()) Q.pop(); 105 memset(col,0,sizeof(col)); 106 for(int i = 1; i <= scnt; ++i) 107 if(din[i] == 0) Q.push(i); 108 while(!Q.empty()){ 109 int x = Q.front(); 110 Q.pop(); 111 if(!col[x]){ 112 col[x] = 1; 113 col[asc[x]] = 2; 114 } 115 for(int i = f1[x]; i != -1; i = n1[i]){ 116 int v = v1[i]; 117 din[v]--; 118 if(din[v] == 0) Q.push(v); 119 } 120 } 121 } 122 123 int main(){ 124 int x,y,xv,yv; 125 char c1,c2; 126 while(scanf("%d%d",&n,&m) != EOF){ 127 if(!n && !m) break; 128 Init(); 129 for(int i = 0; i < m; ++i){ 130 scanf("%d%c %d%c",&x,&c1,&y,&c2); 131 xv = c1 == 'h' ? 0 : 1; 132 yv = c2 == 'h' ? 0 : 1; 133 x = x * 2 + xv; 134 y = y * 2 + yv; 135 Add_edge(x,y ^ 1); 136 Add_edge(y,x ^ 1); 137 } 138 Add_edge(1,0); 139 Tarjan(); 140 int flag = 1; 141 for(int i = 0; i < 2 * n; i += 2){ 142 if(sc[i] == sc[i + 1]){ 143 flag = 0; 144 break; 145 } 146 asc[sc[i]] = sc[i + 1]; 147 asc[sc[i + 1]] = sc[i]; 148 } 149 if(flag == 0){ 150 printf("bad luck\n"); 151 continue; 152 } 153 Build_dag(); 154 Toposort(); 155 for(int i = 2; i < 2 * n; i += 2){ 156 if(col[sc[i]] == col[sc[1]]) printf("%dh ",i / 2); 157 else printf("%dw ",i / 2); 158 } 159 puts(""); 160 } 161 return 0; 162 }