M. Similar Sets 题解(根号分治)

题目链接

题目大意

就是给你\(n\)个集合,所有集合的元素数量不超过\(2e5\)

找出两个集合使得这两个集合至少拥有两个相同的元素,输出任意一组解即可

题目思路

这个写法 真玄学

俗称根号分治 就是对于集合元素的数量进行分类

我是直接看这份题解的链接

对于n个点对的重复问题,确实可以使用\(O(n)\)

比用\(map<pii,int>\)好得多

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=998244353,lim=300;
const double eps=1e-6;
int n,m,k;
int cnt=0;
unordered_map<int,int> ls;
vector<int> g[maxn];
vector<int> b,s;
vector<pair<int,int>> vec[maxn];
int vis[maxn];
int lisan(int x){
    if(ls[x]==0){
        ls[x]=++cnt;
    }
    return ls[x];
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int _;cin>>_;
    while(_--){
        cnt=0;
        ls.clear();
        b.clear();
        s.clear();
        cin>>n;
        for(int i=1;i<=n;i++){
            g[i].clear();
            cin>>k;
            for(int j=1,x;j<=k;j++){
                cin>>x;
                x=lisan(x);
                g[i].push_back(x);
            }
            if(k>=lim){
                b.push_back(i);
            }else{
                s.push_back(i);
            }
        }
        for(int i=1;i<=cnt;i++){
            vec[i].clear();
        }
        bool flag=0;
        for(auto id:b){
            if(flag) break;
            for(int j=0;j<g[id].size();j++){
                int x=g[id][j];
                vis[x]=1;
            }
            for(int i=1;i<=n;i++){
                if(i==id) continue;
                int cnt=0;
                for(int j=0;j<g[i].size();j++){
                    cnt+=vis[g[i][j]];
                }
                if(cnt>=2){
                    cout<<i<<" "<<id<<'\n';
                    flag=1;
                    break;
                }
            }
            for(int j=0;j<g[id].size();j++){
                int x=g[id][j];
                vis[x]=0;
            }
        }
        for(auto id:s){
            if(flag) break;
            for(int j=0;j<g[id].size();j++){
                if(flag) break;
                for(int k=j+1;k<g[id].size();k++){
                    int x=g[id][j],y=g[id][k];
                    if(x>y) swap(x,y);
                    vec[x].push_back({y,id});
                }
            }
        }
        for(int i=1;i<=cnt;i++){
            if(flag) break;
            for(auto j:vec[i]){
                int x=j.fi,y=j.se;
                if(vis[x]){
                    cout<<vis[x]<<" "<<y<<'\n';
                    flag=1;
                    break;
                }
                vis[x]=y;
            }
             for(auto j:vec[i]){
                int x=j.fi,y=j.se;
                vis[x]=0;
            }
        }
        if(!flag){
            cout<<-1<<'\n';
        }
    }
    return 0;
}

posted @ 2021-09-09 17:09  hunxuewangzi  阅读(126)  评论(0编辑  收藏  举报