28. AtCoder-Find 4-cycle
作者:互联网
题目链接:Find 4-cycle
给定一个二分图,一边有 \(3\times 10^5\) 个点,另一边只有 \(3\times 10^3\) 个点,让你找一个长度为 \(4\) 的环。
首先,在二分图上的四元环肯定是左边两个点右边两个点,两两之间有边。
容易发现 \(3\times 10^3\) 这个数很小,可以从这个角度想一些比较暴力的做法,比如暴力枚举任意两个点的组合。
但是直接枚举所有组合的复杂度还是过高了,比如这样做
for (int u = s + 1; u < s + t; ++u) {
for (int& to : g[u])
deg[to]++;
for (int v = u + 1; v <= s + t; ++v) {
for (int& to : g[v])
deg[to]++;
// do something
for (int& to : g[v])
deg[to]--;
}
for (int& to : g[u])
deg[to]--;
}
的复杂度大概是 \(O(t|E|)\),是过不去的。
所以要换一个角度,如果固定了 \((u,v)\),只需要另一端的两个点均与 \((u,v)\) 有边就行了。那么先开一个 \(t^2\) 大小的数组,然后枚举大集合里每个点能到达的 \((u,v)\),如果数组中 \((u,v)\) 处的值为 \(0\),说明之前没有过这样的点,将当前点填进去;否则就找到了一个四元环。
这种做法的复杂度是 \(O(s+|E|+t^2)\),因为数组中的每个位置最多赋值一次。
代码:
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
using ll = long long;
const int maxn = 3e5 + 5000;
const int maxt = 3e3 + 5;
int s, t, m;
vector<int> g[maxn];
int vis[maxt][maxt];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> s >> t >> m;
for (int i = 1, u, v; i <= m; ++i) {
cin >> u >> v;
if (u > v) swap(u, v);
g[u].push_back(v - s);
}
for (int i = 1; i <= s; ++i) {
for (auto&& u : g[i]) {
for (auto&& v : g[i]) {
if (u == v) continue;
if (vis[u][v]) {
cout << vis[u][v] << " " << u + s << " " << i << " " << v + s << endl;
return 0;
}
vis[u][v] = i;
}
}
}
cout << -1 << endl;
return 0;
}
标签:AtCoder,10,int,复杂度,28,maxt,times,using,Find 来源: https://www.cnblogs.com/theophania/p/p28.html