zoukankan      html  css  js  c++  java
  • 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<<'
    ';
                        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<<'
    ';
                        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<<'
    ';
            }
        }
        return 0;
    }
    
    
    不摆烂了,写题
  • 相关阅读:
    【(高职专科组)第十一届蓝桥杯省模拟赛答案】给定一个数列,请问找出元素之间最大的元素距离。
    【(高职专科组)第十一届蓝桥杯省模拟赛答案】给定一个数列,请问数列中最长的递增序列有多长。
    POJ 2391 二分+最大流
    HDU 4529 状压dp
    NYOJ 747贪心+dp
    NYOJ 745 dp
    HDU 2686 / NYOJ 61 DP
    HDU 4313树形DP
    HDU 4303 树形DP
    POJ 2342 树形DP
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15247893.html
Copyright © 2011-2022 走看看