zoukankan      html  css  js  c++  java
  • hdu 2473 Junk-Mail Filter (暴力并查集)

    Problem - 2473

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

      先解释题意,这是一个模拟处理垃圾邮件的问题。垃圾邮件要根据它们的性质进行分类。对于10w个邮件,操作M是这两个邮件具有相同的属性,属性是可以传递的,也就是说,1和2有相同属性,2和3有相同属性,那么1和3就有相同属性。操作S是将这个邮件分离出来,不和任何的邮件有相同属性。最后问不同属性的邮件有多少种。这么看来,这是一个并查集。网上的正解,是把那个删除的结点当成虚拟结点,继续放在那里。然后重新开一个新的结点来存放分离出来的结点。

      而我的做法则是直接构造并查集树,我的树是会记录子结点有那些的,更新的时候就只能直接暴力更新了。

    代码如下:

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <set>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <stack>
      7 
      8 using namespace std;
      9 
     10 const int N = 111111;
     11 stack<int> tmp;
     12 
     13 struct MFS {
     14     set<int> sn[N];
     15     int fa[N];
     16     void init() { for (int i = 0; i < N; i++) fa[i] = i, sn[i].clear(), sn[i].insert(i);}
     17     int find(int x) {
     18         while (!tmp.empty()) tmp.pop();
     19         while (fa[x] != x) {
     20             tmp.push(x);
     21             sn[fa[x]].erase(x);
     22             x = fa[x];
     23         }
     24         while (!tmp.empty()) {
     25             fa[tmp.top()] = x;
     26             sn[x].insert(tmp.top());
     27             tmp.pop();
     28         }
     29         return x;
     30     }
     31     void merge(int x, int y) {
     32         int fx = find(x), fy = find(y);
     33         if (fx == fy) return ;
     34         sn[fa[fy]].erase(fy);
     35         fa[fy] = fx;
     36         sn[fx].insert(fy);
     37     }
     38     void reset(int x) {
     39         set<int>::iterator si = sn[x].begin();
     40         if (fa[x] == x) {
     41             if (*si == x) si++;
     42             if (si == sn[x].end()) return ;
     43             int t = *si;
     44             fa[t] = t;
     45             sn[t].insert(t);
     46             si++;
     47             while (si != sn[x].end()) {
     48                 if (*si == x) { si++; continue;}
     49                 fa[*si] = t;
     50                 sn[t].insert(*si);
     51                 si++;
     52             }
     53         } else {
     54             int fx = find(x);
     55             sn[fx].erase(x);
     56             while (si != sn[x].end()) {
     57                 fa[*si] = fx;
     58                 sn[fx].insert(*si);
     59                 si++;
     60             }
     61         }
     62         fa[x] = x;
     63         sn[x].clear();
     64         sn[x].insert(x);
     65     }
     66 } mfs;
     67 bool vis[N];
     68 
     69 int main() {
     70 //    freopen("in", "r", stdin);
     71     int n, m, x, y, cas = 1;
     72     char op[3];
     73     while (~scanf("%d%d", &n, &m) && (n || m)) {
     74         mfs.init();
     75         for (int i = 0; i < m; i++) {
     76             scanf("%s", op);
     77             if (op[0] == 'M') {
     78                 scanf("%d%d", &x, &y);
     79                 //mfs.reset(y);
     80                 mfs.merge(x, y);
     81             } else {
     82                 scanf("%d", &x);
     83                 mfs.reset(x);
     84             }
     85 //            for (int i = 0; i < 3; i++) cout << mfs.fa[i] << ' '; cout << endl;
     86         }
     87         memset(vis, 0, sizeof(vis));
     88         int cnt = 0;
     89         for (int i = 0, t; i < n; i++) {
     90             t = mfs.find(i);
     91             if (vis[t]) continue;
     92             cnt++;
     93             vis[t] = true;
     94         }
     95         printf("Case #%d: %d
    ", cas++, cnt);
     96     }
     97     return 0;
     98 }
     99 
    100 /*
    101 5 6
    102 M 0 1
    103 M 1 2
    104 M 1 3
    105 S 1
    106 M 1 2
    107 S 3
    108 
    109 3 4
    110 M 1 2
    111 M 0 1
    112 S 1
    113 S 0
    114 
    115 0 0
    116 */
    View Code

      用虚拟结点的方法将会尽快更新。

     

     

    ——written by Lyon

  • 相关阅读:
    phoneGap
    backbonejs使用
    优化后的光标插件
    选择文本,范围
    js最佳继承范型
    深入理解事件捕获冒泡
    keyCode,charCode,which
    与IE奋战的血泪史
    【程序员的自我修养】如何使用IRC
    【程序员的自我修养】写给新手程序员的一封信
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_2473_Lyon.html
Copyright © 2011-2022 走看看