POJ2723 Get Luffy Out
2-sat,我们想对于一对钥匙关系应该是a&b=0即不能同时选
对于一扇门而言应该为a|b=1即要至少选一个
建图二分即可
By:大奕哥
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 const int N=1e4+10,M=1e7+8; 10 int ecnt,n,m,nn,top,num,cnt; 11 int head[N],low[N],dfn[N],col[N],vis[N],s[N]; 12 struct node 13 { 14 int a,b; 15 }key[N],door[N]; 16 struct edge 17 { 18 int to,nex; 19 }e[M]; 20 vector<int>E[N]; 21 void add(int x,int y) 22 { 23 e[++ecnt].to=y;e[ecnt].nex=head[x];head[x]=ecnt; 24 } 25 void init() 26 { 27 ecnt=cnt=num=top=0; 28 memset(head,0,sizeof(head)); 29 memset(low,0,sizeof(low)); 30 memset(dfn,0,sizeof(dfn)); 31 memset(vis,0,sizeof(vis)); 32 memset(col,0,sizeof(col)); 33 memset(s,-1,sizeof(s)); 34 } 35 void dfs(int x) 36 { 37 vis[x]=1;s[++top]=x; 38 low[x]=dfn[x]=++cnt; 39 for(int i=head[x];i;i=e[i].nex) 40 { 41 int y=e[i].to; 42 if(!dfn[y]) 43 { 44 dfs(y); 45 low[x]=min(low[x],low[y]); 46 } 47 else if(vis[y]) 48 { 49 low[x]=min(low[x],dfn[y]); 50 } 51 } 52 if(low[x]==dfn[x]) 53 { 54 num++; 55 while(s[top+1]!=x) 56 { 57 int a=s[top--]; 58 vis[a]=0; 59 col[a]=num; 60 } 61 } 62 return; 63 } 64 bool two_Sat(int mid) 65 { 66 init(); 67 for(int i=0;i<n;++i) 68 { 69 add(key[i].a+nn,key[i].b);//1&1=1 70 add(key[i].b+nn,key[i].a); 71 } 72 for(int i=0;i<mid;++i) 73 { 74 add(door[i].a,door[i].b+nn);//0|0=0 75 add(door[i].b,door[i].a+nn); 76 } 77 for(int i=0;i<nn*2;++i) 78 if(!dfn[i])dfs(i); 79 for(int i=0;i<nn;++i) 80 { 81 if(col[i]==col[i+nn])return 0; 82 } 83 return 1; 84 } 85 int solve() 86 { 87 int l=0,r=m,ans=0; 88 while(l<=r) 89 { 90 int mid=l+r>>1; 91 if(two_Sat(mid))ans=mid,l=mid+1; 92 else r=mid-1; 93 } 94 return ans; 95 } 96 int main() 97 { 98 while(~scanf("%d%d",&n,&m)) 99 { 100 if(!n&&!m)break; 101 nn=n*2; 102 for(int i=0;i<n;++i)scanf("%d%d",&key[i].a,&key[i].b); 103 for(int i=0;i<m;++i)scanf("%d%d",&door[i].a,&door[i].b); 104 printf("%d\n",solve()); 105 } 106 return 0; 107 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。