题意
题解
题没什么难的。说一下一个坑点。
题目说的是有
n
n
对钥匙,就有个钥匙,就有
4∗n
4
∗
n
个布尔变量。
被这个坑了半天。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e5+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax], tot;
struct edge {
int to, nxt;
}e[nmax];
typedef pair<int, int> pii;
int low[10005], dfn[10005], color[10005], ss[10005], st, dfs_clock, scc, doorcnt, keyscnt;
bool instack[10005];
pii doors[10005], keys[10005];
int n , m;
void add_edge(int u, int v) {
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
void init() {
memset(head ,-1, sizeof head);
memset(low, 0, sizeof low);
memset(dfn, 0, sizeof dfn);
memset(color, 0, sizeof color);
memset(head, -1, sizeof head);
tot = st = dfs_clock = scc = 0;
}
void tarjan(int u) {
low[u] = dfn[u] = ++dfs_clock;
ss[st++] = u ;
instack[u] = true;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(instack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) {
scc ++;
int tmp = 0;
while(1) {
tmp = ss[--st];
color[tmp] = scc;
instack[tmp] = false;
if(tmp == u)
break;
}
}
}
bool check(int x) {
memset(low, 0, sizeof low);
memset(dfn, 0, sizeof dfn);
memset(instack, 0, sizeof instack);
memset(color, 0, sizeof color);
memset(head, -1, sizeof head);
tot = st = dfs_clock = scc = 0;
for(int i = 1; i <= n; ++i) {
add_edge(keys[i].first, keys[i].second + 2 * n);
add_edge(keys[i].second, keys[i].first + 2 * n);
}
for(int i = 1; i <= x; ++i) {
add_edge(doors[i].first + 2 * n, doors[i].second);
add_edge(doors[i].second + 2 * n, doors[i].first);
}
for(int i = 1; i <= 4 * n; ++i) {
if(!dfn[i])
tarjan(i);
}
for(int i = 1; i <= 2 * n; ++i) {
if(color[i] == color[i+ 2 * n])
return false;
}
return true;
}
int main(){
while(scanf("%d %d", &n, &m) != EOF) {
if(n == 0 && m == 0)
break;
init();
int u , v;
for(int i = 1; i <= n; ++i) {
scanf("%d %d", &keys[i].first, &keys[i].second);
keys[i].first ++;
keys[i].second ++;
}
for(int i = 1; i <= m; ++i) {
scanf("%d %d", &doors[i].first, &doors[i].second);
doors[i].first ++;
doors[i].second ++;
}
int ans = 0, l = 0 , r = m;
while(l <= r) {
int mid = (l + r) >>1;
if(check(mid)) {
ans = mid;
l = mid + 1;
}else r = mid - 1;
}
printf("%d\n",ans);
}
return 0;
}