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 }