zoukankan      html  css  js  c++  java
  • CF1468M Similar Sets 解题报告

    CF1468M Similar Sets解题报告:

    更好的阅读体验

    题意

    定义两个集合相似当且仅当这两个集合有至少两个相同的元素,给定若干个集合,输出一对相似集合或者报告无解。

    (1leqslant sum|S|leqslant 2 imes 10^5)

    分析

    下面设 (m=sum|S|)

    看到 2e5 考虑根号分治,设集合大小大于 (sqrt m) 的点为大集合,其余为小集合,那么对于每个大集合,我们标记它所有元素,并枚举每个集合判断,由于大集合只会有根号个,所以复杂度是 (O(msqrt m)) 的。

    对于每个小集合,我们枚举其中两个元素并记录下来,然后判断有没有重复的点对,精细实现以下就是 (O(msqrt m))。(具体就是固定第一维,第二维用桶统计)

    代码

    实现需要精细一点,否则会爆空间。

    #include<stdio.h>
    #include<vector>
    #include<map>
    #include<math.h>
    using namespace std;
    const int maxn=100005,maxm=200005;
    int T,n,m,B,x,y,tot,flg;
    int vis[maxm];
    vector<int>v[maxn];
    vector< pair<int,int> >w[maxm];
    map<int,int>mp;
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n),mp.clear(),m=x=y=tot=flg=0;
    		for(int i=1,k;i<=n;i++){
    			scanf("%d",&k),m+=k,v[i].clear();
    			for(int j=0,x;j<k;j++){
    				scanf("%d",&x);
    				if(mp[x]==0)
    					mp[x]=++tot,vis[tot]=0,w[tot].clear();
    				x=mp[x],v[i].push_back(x);
    			}
    		}
    		B=sqrt(m)/2;
    		for(int i=1;i<=n;i++){
    			if(v[i].size()>B){
    				for(int j=0;j<v[i].size();j++)
    					vis[v[i][j]]=1;
    				for(int j=1;j<=n;j++){
    					if(j==i)
    						continue;
    					int cnt=0;
    					for(int k=0;k<v[j].size();k++)
    						cnt+=vis[v[j][k]];
    					if(cnt>=2){
    						flg=1,printf("%d %d
    ",i,j);
    						break;
    					}
    				}
    				for(int j=0;j<v[i].size();j++)
    					vis[v[i][j]]=0;
    			}
    			if(flg)
    				break;
    		}
    		if(flg)
    			continue;
    		for(int i=1;i<=n;i++)
    			if(v[i].size()<=B)
    				for(int j=0;j<v[i].size();j++)
    					for(int k=j+1;k<v[i].size();k++)
    						w[min(v[i][j],v[i][k])].push_back(make_pair(max(v[i][j],v[i][k]),i));
    		for(int i=1;i<=tot;i++){
    			for(int j=0;j<w[i].size();j++){
    				if(vis[w[i][j].first]){
    					flg=1,printf("%d %d
    ",vis[w[i][j].first],w[i][j].second);
    					break;
    				}
    				vis[w[i][j].first]=w[i][j].second;
    			}
    			if(flg==1)
    				break;
    			for(int j=0;j<w[i].size();j++)
    				vis[w[i][j].first]=0;
    		}
    		if(flg==0)
    			puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    QT类型转换(九种转换)
    QString类的使用(无所不包,极其方便)
    在TreeWidget中增加右键菜单功能 以及TreeWidget的基本用法
    在ubuntu上安装nodejs[开启实时web时代]
    排序和搜索
    new关键字
    Dynamicaly Typed(动态定型), Objective-C Runtime Programming
    图形化机构树
    java-并发之高性能对象
    委托的基本理解与使用
  • 原文地址:https://www.cnblogs.com/xiaoziyao/p/15234586.html
Copyright © 2011-2022 走看看