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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}