您的位置:首页 > 大数据 > 人工智能

hdu 2473 Junk-Mail Filter (暴力并查集)

2013-07-18 00:50 489 查看
Problem - 2473

  为什么标题写的是暴力并查集?因为我的解法跟网上的有所不同,方法暴力很多。

  先解释题意,这是一个模拟处理垃圾邮件的问题。垃圾邮件要根据它们的性质进行分类。对于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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: