poj 2723 Get Luffy Out (2 -sat + 二分)
http://poj.org/problem?id=2723
题意:
有2n把钥匙,分成2组,给你每组的钥匙信息,并且每组的钥匙只能用一个。
有m个门,每个门有2个锁,只要打开一个锁这个门就开了。(顺序遇见m个门)
问你最多能够打开多少个门。
通过这道题 ,对 2-sat 有了 进一步的了解。。。。。
2-SAT主要是寻找不相容的点(建图),首先是
我们把钥匙分为 选和不选,A和 !A
对于 第一类 : 没两把钥匙 ,a和b ( 必然关系 ) 选 a 不选 b(a->!b) ,选 b 不选 a(b->!a);
对于 第二类:
每一扇门 有 a 锁和 b 锁,不开a 必开 b (!a->b),,不开b 必开 a(!b->a),///一开始 建图减成了 a-> !b 和 b-> !a (这样是 不对的
因为每扇门至少要开一把锁,我们要找的是 必须的 关系
) 因为 门 是 顺序的 ,所以要 二分枚举。
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000000
16 #define mx 1<<60
17 #define ll __int64
18 const double pi = acos(-1.0);
19 const int maxn = 5000;
20 using namespace std;
21 int top,num,bcnt,belong[maxn],instack[maxn],stack[maxn],dfn[maxn],low[maxn];
22 int n ,m;
23 int a[maxn],b[maxn],c[maxn],d[maxn];
24 struct pnode
25 {
26 int to;
27 int next;
28 }p[maxn*2];
29
30 int cnt ,next[maxn];
31 void add(int u,int v)
32 {
33 p[cnt].to = v;
34 p[cnt].next = next[u];
35 next[u] = cnt++;
36
37 }
38 void tarjan(int i)
39 {
40 int j,k;
41 dfn[i] = low[i] = ++num;
42 stack[++top] = i;
43 instack[i] = 1;
44 for(k = next[i] ; k != -1;k = p[k].next)
45 {
46
47 j = p[k].to ;
48 if(!dfn[j])
49 {
50 tarjan(j);
51 if(low[j] < low[i]) low[i] = low[j] ;
52 }
53 else
54 {
55 if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
56 }
57
58 }
59 if(dfn[i] == low[i])
60 {
61 bcnt++;
62 do
63 {
64 j = stack[top--];
65 instack[j] = 0 ;
66 belong[j] = bcnt ;
67 }while(j != i);
68 }
69 }
70 void solve()
71 {
72 int i, l;
73 for(i =0 ; i <= n*4;i++)
74 {
75 dfn[i] = low[i] = instack[i] = stack[i] = belong[i] = 0;
76 }
77 top = bcnt = num = 0;
78 for(i = 0 ; i < n*4;i++)
79 {
80 if(!dfn[i])tarjan(i);
81 }
82
83
84
85 }
86 void init()
87 {
88 CL(next,-1);
89 cnt = 0 ;
90
91 }
92 bool judge()
93 {
94 for(int i = 0 ; i < 2*n;i++)
95 {
96 if(belong[i] == belong[i + 2*n])
97 return false ;
98 }
99 return true ;
100 }
101 int main()
102 {
103 int i,j;
104
105 //freopen("data.txt","r",stdin) ;
106
107 while(scanf("%d%d",&n,&m),n+m)
108 {
109
110 for(i = 1 ;i <= n;i++)
111 {
112 scanf("%d%d",&a[i],&b[i]);
113
114 }
115 for(i = 1;i <= m;i++)
116 {
117 scanf("%d%d",&c[i],&d[i]);
118
119 }
120 int l = 0,r = m ;
121 int ans = 0 ;
122 while(l <= r)
123 {
124 init();
125 int mid = (l+r)>>1;
126 for(i = 1; i<= n;i++)
127 {
128 add(a[i],b[i] + n*2);
129 add(b[i],a[i] + n*2);
130 }
131 for(i = 1;i <= mid;i++)
132 {
133 add(c[i] + n*2,d[i] );
134 add(d[i] + n*2,c[i] );
135 }
136 solve() ;
137 if(judge())
138 {
139
140 l = mid + 1;
141 ans = mid ;
142 }
143 else r = mid - 1;
144 }
145 printf("%d\n",ans);
146 }
147 }
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000000
16 #define mx 1<<60
17 #define ll __int64
18 const double pi = acos(-1.0);
19 const int maxn = 5000;
20 using namespace std;
21 int top,num,bcnt,belong[maxn],instack[maxn],stack[maxn],dfn[maxn],low[maxn];
22 int n ,m;
23 int a[maxn],b[maxn],c[maxn],d[maxn];
24 struct pnode
25 {
26 int to;
27 int next;
28 }p[maxn*2];
29
30 int cnt ,next[maxn];
31 void add(int u,int v)
32 {
33 p[cnt].to = v;
34 p[cnt].next = next[u];
35 next[u] = cnt++;
36
37 }
38 void tarjan(int i)
39 {
40 int j,k;
41 dfn[i] = low[i] = ++num;
42 stack[++top] = i;
43 instack[i] = 1;
44 for(k = next[i] ; k != -1;k = p[k].next)
45 {
46
47 j = p[k].to ;
48 if(!dfn[j])
49 {
50 tarjan(j);
51 if(low[j] < low[i]) low[i] = low[j] ;
52 }
53 else
54 {
55 if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
56 }
57
58 }
59 if(dfn[i] == low[i])
60 {
61 bcnt++;
62 do
63 {
64 j = stack[top--];
65 instack[j] = 0 ;
66 belong[j] = bcnt ;
67 }while(j != i);
68 }
69 }
70 void solve()
71 {
72 int i, l;
73 for(i =0 ; i <= n*4;i++)
74 {
75 dfn[i] = low[i] = instack[i] = stack[i] = belong[i] = 0;
76 }
77 top = bcnt = num = 0;
78 for(i = 0 ; i < n*4;i++)
79 {
80 if(!dfn[i])tarjan(i);
81 }
82
83
84
85 }
86 void init()
87 {
88 CL(next,-1);
89 cnt = 0 ;
90
91 }
92 bool judge()
93 {
94 for(int i = 0 ; i < 2*n;i++)
95 {
96 if(belong[i] == belong[i + 2*n])
97 return false ;
98 }
99 return true ;
100 }
101 int main()
102 {
103 int i,j;
104
105 //freopen("data.txt","r",stdin) ;
106
107 while(scanf("%d%d",&n,&m),n+m)
108 {
109
110 for(i = 1 ;i <= n;i++)
111 {
112 scanf("%d%d",&a[i],&b[i]);
113
114 }
115 for(i = 1;i <= m;i++)
116 {
117 scanf("%d%d",&c[i],&d[i]);
118
119 }
120 int l = 0,r = m ;
121 int ans = 0 ;
122 while(l <= r)
123 {
124 init();
125 int mid = (l+r)>>1;
126 for(i = 1; i<= n;i++)
127 {
128 add(a[i],b[i] + n*2);
129 add(b[i],a[i] + n*2);
130 }
131 for(i = 1;i <= mid;i++)
132 {
133 add(c[i] + n*2,d[i] );
134 add(d[i] + n*2,c[i] );
135 }
136 solve() ;
137 if(judge())
138 {
139
140 l = mid + 1;
141 ans = mid ;
142 }
143 else r = mid - 1;
144 }
145 printf("%d\n",ans);
146 }
147 }