其他分享
首页 > 其他分享> > 28. AtCoder-Find 4-cycle

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