hdu 2473 Junk-Mail Filter (暴力并查集)
2013-07-18 00:50
489 查看
Problem - 2473
为什么标题写的是暴力并查集?因为我的解法跟网上的有所不同,方法暴力很多。
先解释题意,这是一个模拟处理垃圾邮件的问题。垃圾邮件要根据它们的性质进行分类。对于10w个邮件,操作M是这两个邮件具有相同的属性,属性是可以传递的,也就是说,1和2有相同属性,2和3有相同属性,那么1和3就有相同属性。操作S是将这个邮件分离出来,不和任何的邮件有相同属性。最后问不同属性的邮件有多少种。这么看来,这是一个并查集。网上的正解,是把那个删除的结点当成虚拟结点,继续放在那里。然后重新开一个新的结点来存放分离出来的结点。
而我的做法则是直接构造并查集树,我的树是会记录子结点有那些的,更新的时候就只能直接暴力更新了。
代码如下:
View Code
用虚拟结点的方法将会尽快更新。
——written by Lyon
为什么标题写的是暴力并查集?因为我的解法跟网上的有所不同,方法暴力很多。
先解释题意,这是一个模拟处理垃圾邮件的问题。垃圾邮件要根据它们的性质进行分类。对于10w个邮件,操作M是这两个邮件具有相同的属性,属性是可以传递的,也就是说,1和2有相同属性,2和3有相同属性,那么1和3就有相同属性。操作S是将这个邮件分离出来,不和任何的邮件有相同属性。最后问不同属性的邮件有多少种。这么看来,这是一个并查集。网上的正解,是把那个删除的结点当成虚拟结点,继续放在那里。然后重新开一个新的结点来存放分离出来的结点。
而我的做法则是直接构造并查集树,我的树是会记录子结点有那些的,更新的时候就只能直接暴力更新了。
代码如下:
#include <iostream> #include <algorithm> #include <set> #include <cstring> #include <cstdio> #include <stack> using namespace std; const int N = 111111; stack<int> tmp; struct MFS { set<int> sn ; int fa ; void init() { for (int i = 0; i < N; i++) fa[i] = i, sn[i].clear(), sn[i].insert(i);} int find(int x) { while (!tmp.empty()) tmp.pop(); while (fa[x] != x) { tmp.push(x); sn[fa[x]].erase(x); x = fa[x]; } while (!tmp.empty()) { fa[tmp.top()] = x; sn[x].insert(tmp.top()); tmp.pop(); } return x; } void merge(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) return ; sn[fa[fy]].erase(fy); fa[fy] = fx; sn[fx].insert(fy); } void reset(int x) { set<int>::iterator si = sn[x].begin(); if (fa[x] == x) { if (*si == x) si++; if (si == sn[x].end()) return ; int t = *si; fa[t] = t; sn[t].insert(t); si++; while (si != sn[x].end()) { if (*si == x) { si++; continue;} fa[*si] = t; sn[t].insert(*si); si++; } } else { int fx = find(x); sn[fx].erase(x); while (si != sn[x].end()) { fa[*si] = fx; sn[fx].insert(*si); si++; } } fa[x] = x; sn[x].clear(); sn[x].insert(x); } } mfs; bool vis ; int main() { // freopen("in", "r", stdin); int n, m, x, y, cas = 1; char op[3]; while (~scanf("%d%d", &n, &m) && (n || m)) { mfs.init(); for (int i = 0; i < m; i++) { scanf("%s", op); if (op[0] == 'M') { scanf("%d%d", &x, &y); //mfs.reset(y); mfs.merge(x, y); } else { scanf("%d", &x); mfs.reset(x); } // for (int i = 0; i < 3; i++) cout << mfs.fa[i] << ' '; cout << endl; } memset(vis, 0, sizeof(vis)); int cnt = 0; for (int i = 0, t; i < n; i++) { t = mfs.find(i); if (vis[t]) continue; cnt++; vis[t] = true; } printf("Case #%d: %d\n", cas++, cnt); } return 0; } /* 5 6 M 0 1 M 1 2 M 1 3 S 1 M 1 2 S 3 3 4 M 1 2 M 0 1 S 1 S 0 0 0 */
View Code
用虚拟结点的方法将会尽快更新。
——written by Lyon
相关文章推荐
- (step5.1.2)hdu 2473(Junk-Mail Filter——并查集)
- HDU-2473-Junk-Mail Filter-并查集的删除操作
- HDU 2473 Junk-Mail Filter 并查集 删点
- HDU-2473 Junk-Mail Filter(并查集的删除)
- HDU 2473 Junk-Mail Filter 并查集 惰性删除
- HDU 2473 Junk-Mail Filter (删点并查集)
- HDU 2473 Junk-Mail Filter 删点并查集
- hdu 2473 Junk-Mail Filter(并查集+虚拟节点)
- hdu_2473 Junk-Mail Filter 并查集
- HDU 2473 Junk_Mail Filter(并查集(虚点))
- HDU 2473-Junk-Mail Filter-并查集删除
- HDU 2473 Junk-Mail Filter 删点并查集
- HDU 2473 ( Junk-Mail Filter ) (并查集删除操作)
- hdu 2473 Junk-Mail Filter(并查集(虚拟父节点))
- HDU 2473 Junk-Mail Filter 删点并查集
- HDU 2473 Junk-Mail Filter (并查集的删除操作)
- HDU 2473 Junk-Mail Filter(并查集的删除操作)
- Hdu 2473 Junk-Mail Filter (并查集的删除)
- hdu 2473 Junk-Mail Filter【并查集好题、建立虚拟节点】
- HDU 2473 Junk-Mail Filter(并查集删除节点)