zoukankan      html  css  js  c++  java
  • BZOJ1098 [POI2007]办公楼biu

    题目蓝链

    Solution

    这题显然就是一道BFS的题,但这道题的边数很多,我们怎么保证是(mathcal{O}(n))级别的呢

    我们只需要维护一个并查集(模拟链表),表示当前还未访问的点。然后我们从当前节点往所有与当前点连了边的未访问到的节点扩展,每到一个点就在链表删掉当前当前的点。这样就能保证时间复杂度了

    至于怎么快速判断两点之间有没有边,我们可以直接把边排好序之后加入到链式前向星,然后在判断的时候直接(tow point)判断就可以了

    时间复杂度(mathcal{O}(n + m))

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int maxn = 1e5 + 10;
    const int maxm = 2e6 + 10;
    
    int n, m;
    int Begin[maxn], Next[maxm << 1], To[maxm << 1], e = -1;
    
    inline void add(int x, int y) {
    	To[++e] = y, Next[e] = Begin[x], Begin[x] = e;
    }
    
    namespace DSU {
    	int fa[maxn];
    	void init() { for (int i = 1; i <= n + 1; i++) fa[i] = i; }
    	int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    	void merge(int x, int y) { x = find(x), y = find(y); if (x != y) fa[x] = y; }
    }
    
    bool v[maxn];
    int cnt, ans[maxn];
    
    void dfs(int now) {
    	v[now] = 1; ++cnt;
    	DSU::merge(now, now + 1);
    	for (int i = DSU::find(1), p = Begin[now]; i <= n; i = DSU::find(i + 1)) {
    		bool fg = 1;
    		for (; p + 1 && To[p] <= i; p = Next[p]) if (To[p] == i) { fg = 0; break; }
    		if (fg) dfs(i);
    	}
    }
    
    struct edge {
    	int x, y;
    	bool operator < (const edge &t) const { return x == t.x ? y > t.y : x > t.x; }
    }eg[maxm];
    
    int main() {
    #ifdef xunzhen
    	freopen("set.in", "r", stdin);
    	freopen("set.out", "w", stdout);
    #endif
    
    	memset(Begin, -1, sizeof Begin);
    	n = read(), m = read();
    	for (int i = 1; i <= m; i++) {
    		int x = read(), y = read();
    		eg[i] = (edge){x, y};
    	}
    	sort(eg + 1, eg + m + 1);
    	for (int i = 1; i <= m; i++) add(eg[i].x, eg[i].y), add(eg[i].y, eg[i].x);
    
    	DSU::init();
    	for (int i = 1; i <= n; i++)
    		if (!v[i]) cnt = 0, dfs(i), ans[++ans[0]] = cnt;
    
    	printf("%d
    ", ans[0]);
    	sort(ans + 1, ans + ans[0] + 1);
    	for (int i = 1; i <= ans[0]; i++) printf("%d%c", ans[i], i < ans[0] ? ' ' : '
    ');
    
    	return 0;
    }
    

    Summary

    复习一下补图并查集,换了一种常数较小的写法

  • 相关阅读:
    POJ 1887 Testing the CATCHER
    HDU 3374 String Problem
    HDU 2609 How many
    POJ 1509 Glass Beads
    POJ 1458 Common Subsequence
    POJ 1159 Palindrome
    POJ 1056 IMMEDIATE DECODABILITY
    POJ 3080 Blue Jeans
    POJ 1200 Crazy Search
    软件体系结构的艺术阅读笔记1
  • 原文地址:https://www.cnblogs.com/xunzhen/p/9732146.html
Copyright © 2011-2022 走看看