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 }

 

posted @ 2018-01-18 16:06  大奕哥&VANE  阅读(181)  评论(0编辑  收藏  举报