POJ 2723 2-SAT
题意:
有2n把钥匙,每2个一组,给你每组的钥匙信息,并且每组的钥匙只能用一个。有m个门,每个门有2个锁,只要打开一个锁这个门就开了。问你最多能够打开多少个门。
PS:打开门必须是有序的,即你想要打开i就必须之前已经打开了i-1
分析:
不知道我这样做的人多不多。
由于有序性,所以二份答案是必须的
我是把一个钥匙a(不是一组钥匙)拆成两个点a0和a1,分别表示没有取过和取过,对于和他同组的钥匙b,连两条边,a1-->b0和b1-->a0,表示取了a钥匙就不能再取b钥匙
对于每层的两把锁,c和d,连c0-->d1,d0-->c1,表示c钥匙不取则d钥匙必须取,d钥匙不取则c钥匙必须取,也就是说,必须要有一个钥匙来开这个锁
View Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 using namespace std; 6 const int N=(1<<13)+100000; 7 const int M=(1<<25)+1000000; 8 int head[N],next[M],to[M],dir[N],ans,n,m,cnt,dfn[N],low[N],belong[N],mid,stack[N],p,divg,t,do1[M],do2[M]; 9 bool fg[N]; 10 void read() 11 { 12 for(int i=1,a,b;i<=n;i++) 13 { 14 scanf("%d%d",&a,&b),a++,b++; 15 dir[a]=b,dir[b]=a; 16 } 17 for(int i=1;i<=m;i++) scanf("%d%d",&do1[i],&do2[i]),do1[i]++,do2[i]++; 18 } 19 inline void add(int u,int v) 20 { 21 to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++; 22 } 23 void create() 24 { 25 memset(head,-1,sizeof head); 26 memset(dfn,0,sizeof dfn); 27 memset(belong,0,sizeof belong); 28 memset(fg,0,sizeof fg); 29 cnt=0; divg=0; p=0; t=0; 30 for(int i=1;i<=2*n;i++) add(i,dir[i]+2*n); 31 for(int i=1;i<=mid;i++) 32 add(do1[i]+2*n,do2[i]),add(do2[i]+2*n,do1[i]); 33 } 34 bool judge() 35 { 36 for(int i=1;i<=2*n;i++) 37 if(belong[i]==belong[i+2*n]) return false; 38 return true; 39 } 40 void dfs(int u) 41 { 42 t++; 43 dfn[u]=low[u]=t; 44 stack[++p]=u; fg[u]=true; 45 for(int i=head[u];~i;i=next[i]) 46 { 47 if(!dfn[to[i]]) 48 { 49 dfs(to[i]); 50 low[u]=min(low[u],low[to[i]]); 51 } 52 else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]); 53 } 54 if(dfn[u]==low[u]) 55 { 56 divg++; 57 int tmp=-1; 58 while(tmp!=u) 59 { 60 tmp=stack[p--]; 61 belong[tmp]=divg; 62 fg[tmp]=false; 63 } 64 } 65 } 66 bool tarjan() 67 { 68 create(); 69 for(int i=1;i<=4*n;i++) 70 if(!dfn[i]) dfs(i); 71 if(judge()) return true; 72 else return false; 73 } 74 void go() 75 { 76 int l=0,r=m; 77 while(l<=r) 78 { 79 mid=(l+r)>>1; 80 //printf("%d\n",mid); 81 if(tarjan()) ans=mid,l=mid+1; 82 else r=mid-1; 83 } 84 printf("%d\n",ans); 85 } 86 int main() 87 { 88 while(scanf("%d%d",&n,&m),n||m) 89 { 90 read(); 91 go(); 92 } 93 system("pause"); 94 return 0; 95 }
没有人能阻止我前进的步伐,除了我自己!