You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
3.9 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, k;
int x[N], y[N];
struct Node {
int to, id; // id:哪个房间to:另一只猫猫的号码
};
vector<Node> g[N];
vector<int> S;
bool st[N];
// void getnodes(int u) {
// st[u] = 1;
// S.push_back(u);
// for (auto e : g[u]) {
// int v = e.to;
// if (!st[v]) getnodes(v);
// }
// }
vector<int> C;
int fa[N], pre[N], res[N];
bool fi;
void findcycle(int u) {
st[u] = 1; // u号小猫已经找过房间了
for (auto e : g[u]) { // 遍历u号小猫的每个可用房间
int v = e.to, i = e.id;
if (i == pre[u]) continue; // 不走回头路
if (!st[v]) { // 进入搜索
fa[v] = u, pre[v] = i, findcycle(v);
continue;
}
if (fi) continue;
int q = u;
while (q != v) {
C.push_back(q), res[pre[q]] = (x[pre[q]] == q ? 2 : 1);
q = fa[q];
}
res[i] = (x[i] == u ? 1 : 2);
fi = 1;
C.push_back(v);
}
}
bool chk(int m) {
// 多次二分,清空现场
for (int i = 1; i <= n; i++) g[i].clear();
memset(st, 0, sizeof(st)), memset(pre, 0, sizeof(pre)), memset(fa, 0, sizeof(fa));
// 前m个房间
for (int i = 1; i <= m; i++) {
int u = x[i], v = y[i];
// 无向图建图
g[u].push_back({v, i}); // u这只猫猫可以使用i这个房间另外一个可以使用i房间的猫猫是v号
g[v].push_back({u, i}); // v这只猫猫可以使用i这个房间另外一个可以使用i房间的猫猫是u号
}
for (int i = 1; i <= n; i++) { // 每只猫
if (st[i]) continue; // 如果访问过,就下一个
fi = 0, C.clear(); // fii号小猫在哪个房间里
findcycle(i); // 为i号小猫找房间
if (!fi) return 0; // 如果没有找到合适的房间那么就表示当前的m太小的需要扩大
}
return 1; // 检查通过返回OK
}
void dfs(int u) {
st[u] = 1;
for (auto e : g[u]) {
int v = e.to, i = e.id;
if (st[v] || res[i] != 0) continue;
res[i] = (x[i] == v ? 1 : 2);
dfs(v);
}
}
// void getans(int m) {
// for (int i = 1; i <= n; i++) g[i].clear();
// memset(st, 0, sizeof(st)), memset(pre, 0, sizeof(pre));
// memset(fa, 0, sizeof(fa)), memset(res, 0, sizeof(res));
// for (int i = 1; i <= m; i++) {
// int u = x[i], v = y[i];
// g[u].push_back({v, i}), g[v].push_back({u, i});
// }
// for (int i = 1; i <= n; i++) {
// if (st[i]) continue;
// S.clear();
// getnodes(i);
// fi = 0;
// for (int p : S) st[p] = 0;
// C.clear();
// findcycle(i);
// for (int p : S) st[p] = 0;
// for (int p : C) st[p] = 1;
// for (int p : C) dfs(p);
// for (int p : S) st[p] = 1;
// }
// for (int i = 1; i <= m; i++) cout << res[i] << " ";
// puts("");
// }
int main() {
freopen("cats.in", "r", stdin);
// freopen("cats.out", "w", stdout);
cin >> n >> k; // n只小猫k个房间
for (int i = 1; i <= k; i++) cin >> x[i]; // k个房间可以容纳x[i]的猫猫
for (int i = 1; i <= k; i++) cin >> y[i]; // k个房间可以容纳y[i]的猫猫
int L = 1, R = k, ans = L; // 二分答案
while (L <= R) {
int mid = (L + R) >> 1;
if (chk(mid)) // 如果每个猫猫都可以有房间,那么检查通过,说明房间的数量还是很宽松的
R = mid - 1, ans = mid;
else
L = mid + 1;
}
// 输出数量
cout << ans << endl;
// 输出方案
// getans(ans);
return 0;
}