ABC260F 题解

题面

根据题目描述,原图为二分图,设两侧点集为 \(S,T\),大小为 \(s,t(s\le 3\times 10^5,t\le 3\times 10^3)\)

注意到有四元环当且仅当 \(T\) 中存在一个点对 \((a,b)\) 同时和 \(S\) 中的某两个点连边。

可以先考虑暴力,一种想法是:考虑枚举 \(S\) 中的点 \(c\),设和 \(c\) 连边的点的集合为 \(Tc\)

对所有满足 \(a,b\in Tc,a\neq b\) 的点对打上标记 \(tag(a,b)=c\),表示 \(a,b\) 同时和 \(c\) 有连边。

如果已经被打上标记,说明有四元环 \(a-tag(a,b)-b-c\)

如果到最后都没有出现,输出 \(-1\)

这种做法的时间复杂度是多少?

我们发现 \(T\) 中只有 \(\dfrac{t(t-1)}{2}\) 个点对,根据鸽巢原理,最多打 \(\dfrac{t(t-1)}{2}+1\) 个标记就会重复访问同一个点对,即出现一个四元环。

所以时间复杂度 \(O(s+t^2)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 3e5 + 5, M = 3005;

vector<int> e[N];
int a[M][M], s, t, m;

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> s >> t >> m;
    for(int i = 1; i <= m; i ++)
    {
        int x, y; cin >> x >> y;
        e[x].push_back(y - s);
    }
    for(int i = 1; i <= s; i ++)
    {
        for(int j = 0; j < e[i].size(); j ++)
        {
            for(int k = j + 1; k < e[i].size(); k ++)
            {
                int x = e[i][j], y = e[i][k];
                if(a[x][y])
                {
                    cout << x + s << " " << a[x][y] << " " << y + s << " " << i;
                    return 0;
                }
                a[x][y] = a[y][x] = i;
            }
        }
    }
    cout << -1;

    return 0;
}
posted @ 2024-07-27 16:43  adam01  阅读(30)  评论(0)    收藏  举报