1. 程式人生 > >POJ 3648 Wedding

POJ 3648 Wedding

clu bad () ems 題解 -s else algo 註意

經典2-sat

題解:

把一對夫妻視為一個集合,按淫亂關系建邊

如果有淫亂關系顯然不能都坐在新娘對面

註意要給(1,1+n)連邊保證必須新娘和新郎坐對桌

tarjan縮完點之後,因為tarjan的編號是拓撲的逆序,所以我們在選擇坐在新娘對面的人的時候,只要保證選擇w和h編號較小的即可

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<stack>
 5 #define N 2010
 6 using namespace std;
 7 int n,m,ecnt,dfn[N],low[N],indx,head[N],belong[N],cnt,inst[N],t,ok;
8 char a,b; 9 stack <int> st; 10 struct edge 11 { 12 int u,v,nxt; 13 }e[N*N]; 14 int get(int x) 15 { 16 return (x<=n)?x+n:x-n; 17 } 18 void add(int u,int v) 19 { 20 e[++ecnt].v=v; 21 e[ecnt].u=u; 22 e[ecnt].nxt=head[u]; 23 head[u]=ecnt; 24 } 25 void tar(int u) 26 { 27
dfn[u]=low[u]=++indx; 28 inst[u]=1; 29 st.push(u); 30 for (int i=head[u];i;i=e[i].nxt) 31 { 32 int v=e[i].v; 33 if (!dfn[v]) 34 { 35 tar(v); 36 low[u]=min(low[u],low[v]); 37 } 38 else if (inst[v]==1) 39 low[u]=min(low[u],dfn[v]);
40 } 41 if (dfn[u]==low[u]) 42 { 43 ++cnt; 44 while (1) 45 { 46 t=st.top(); 47 belong[t]=cnt; 48 st.pop(); 49 inst[t]=0; 50 if (t==u) 51 break; 52 } 53 } 54 } 55 void init() 56 { 57 cnt=0; 58 memset(dfn,0,sizeof(dfn)); 59 ecnt=0; 60 memset(head,0,sizeof(head)); 61 memset(low,0,sizeof(low)); 62 memset(inst,0,sizeof(inst)); 63 memset(belong,0,sizeof(belong)); 64 indx=0; 65 ok=1; 66 } 67 int main() 68 { 69 while (scanf("%d%d",&n,&m)!=EOF ) 70 { 71 if (n+m==0) break; 72 init(); 73 int u,v; 74 for (int i=1;i<=m;i++) 75 { 76 scanf("%d%c %d%c",&u,&a,&v,&b); 77 u++,v++; 78 if (a==h) u+=n; 79 if (b==h) v+=n; 80 add(u,get(v)); 81 add(v,get(u)); 82 } 83 add(1,1+n); 84 for (int i=1;i<=2*n;i++) 85 if (!dfn[i]) tar(i); 86 for (int i=1;i<=n && ok==1;i++) 87 if (belong[i]==belong[i+n]) 88 ok=0; 89 if (!ok) 90 { 91 puts("bad luck"); 92 continue; 93 } 94 for (int i=2;i<=n;i++) 95 printf("%d%c%c",i-1,(belong[i]>belong[i+n])?w:h," \n"[i==n]); 96 if (n<2) printf("\n"); 97 } 98 return 0; 99 }

POJ 3648 Wedding