zoukankan      html  css  js  c++  java
  • CodeForces-920E Connected Components? 广度搜索 双向链表 判断联通 大量重复节点的删除

    题目链接:https://cn.vjudge.net/problem/CodeForces-920E

    题意

    给一个补图,问各个联通块有几个元素,升序排列
    注意maxn=2e5, maxm=2e10

    思路

    数据量超大,这本来是并查集专题的一道题
    如果用并查集的话,向上维护一个元素个数,但首先离线建图是个问题O(n^2)
    这样考虑的话,bfs O(n)就是更好的选择
    提交上去TLE,当时写题没仔细算复杂度,set查边+数组判重,加起来貌似O(nlogn+n),至于为什么用set查边,因为数组查边肯定空间太大
    最后查了查题解,判重是链表删除元素,相当于真正的删除了,循环次数大大降低了
    好么,厉害

    提交过程

    CE 头文件
    TLE1 set<pair<int, int>>存边
    TLE2 改成set存边
    WA1-3 忘了为啥WA了...
    AC

    代码

    #include <set>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=2e5+20;
    int n, m, cnt, size[maxn], next[maxn], prev[maxn];
    bool check[maxn];
    set<long long> vis;
    void del(int x){
    	next[prev[x]]=next[x];
    	prev[next[x]]=prev[x];
    }
    
    int bfs(int x){
    	int ans=1;
    	queue<int> que; que.push(x);
    	check[x]=true; del(x);
    	while (que.size()){
    		int node=que.front(); que.pop();
    
    		for (int i=next[0]; i<=n; i=next[i]) if (!check[i] && !vis.count((long long)i*maxn+node)){
    			que.push(i);
    			check[i]=true; del(i);
    			ans++;
    		}
    	}return ans;
    }
    
    int main(void){
    	int to, from;
    	scanf("%d%d", &n, &m);
    	for (int i=0; i<m; i++){
    		scanf("%d%d", &to, &from);
    		vis.insert((long long)to*maxn+from);
    		vis.insert((long long)from*maxn+to);
    	}
    	for (int i=1; i<=n; i++) next[i]=i+1, prev[i]=i-1;
    	next[0]=1; prev[n+1]=n;
    
    	int cnt=0;
    	for (int i=1; i<=n; i++) if (!check[i])
    		size[cnt++]=bfs(i);
    	sort(size, size+cnt);
    	printf("%d
    ", cnt);
    	for (int i=0; i<cnt; i++) printf("%d%c", size[i], " 
    "[i==cnt-1]);
    
    	return 0;
    }
    
    Time Memory Length Lang Submitted
    343ms 16012kB 1067 GNU G++ 5.1.0 2018-07-23 17:51:00
  • 相关阅读:
    2016.10.15先占坑
    2016.10.11先占坑
    2016.10.13先占坑
    2016.10.7先占坑
    main()里面为什么要放String[] args
    对于一个给定的正整数 n ,请你找出一共有多少种方式使 n 表示为若干个连续正整数的和,要求至少包括两个正整数。
    求两个数的最大公约数的三种算法总结
    C++
    Dev-c5.11的使用
    客户端和服务器端的交互(未完待续)
  • 原文地址:https://www.cnblogs.com/tanglizi/p/9385912.html
Copyright © 2011-2022 走看看