• 洛谷1197并查集拆集合


    链接:https://www.luogu.org/problemnew/show/P1197

    题意:一张图,拆开若干次点,问每次拆开后连通分量的个数。

    思路:刚开始想着并查集这么拆集合,后来发现拆集合不好拆,【正难则反】,我们可以反过来思考,拆点变成加点。

    开始把不在破坏序列的点的边连上。处理集合数量。

    然后再安装拆点的逆顺序加点,用并查集维护加点的影响

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 const int maxn = 1e6 + 7;
      5 const int maxm = 1e6 + 7;
      6 
      7 int n, m, first[maxn], sign, pre[maxn];
      8 
      9 int hit[maxn];
     10 bool broke[maxn];
     11 
     12 struct Edge {
     13     int to, w, next;
     14 } edge[maxm];
     15 
     16 void init() {
     17     for(int i = 0; i < n; i ++ ) {
     18         first[i] = -1;
     19     }
     20     sign = 0;
     21 }
     22 
     23 void add_edge(int u, int v, int w) {
     24     edge[sign].to = v;
     25     edge[sign].w = w;
     26     edge[sign].next = first[u];
     27     first[u] = sign ++;
     28 }
     29 
     30 void init_disjoint_set() {
     31     for(int i = 0; i < n; i ++ ) {
     32         pre[i] = i;
     33     }
     34 }
     35 
     36 int findx(int x) {
     37     return pre[x] == x ? x : pre[x] = findx(pre[x]);
     38 }
     39 
     40 void join(int x, int y) {
     41     int fx = findx(x), fy = findx(y);
     42     if(fx != fy) {
     43         pre[fx] = fy;
     44     }
     45 }
     46 
     47 bool same(int x, int y) {
     48     return findx(x) == findx(y);
     49 }
     50 
     51 int main()
     52 {
     53     while(~scanf("%d %d", &n, &m)) {
     54         init();
     55         init_disjoint_set();
     56         for(int i = 1; i <= m; i ++ ) {
     57             int u, v;
     58             scanf("%d %d", &u, &v);
     59             add_edge(u, v, 1);
     60             add_edge(v, u, 1);
     61         }
     62         int num;
     63         memset(hit, 0, sizeof(hit));
     64         memset(broke, 0, sizeof(broke));
     65         scanf("%d", &num);
     66         for(int i = 1; i <= num; i ++ ) {
     67             scanf("%d", &hit[i]);
     68             broke[ hit[i] ] = 1;
     69         }
     70         int tot = n - num;
     71         for(int i = 0; i < n; i ++ ) {
     72             if(broke[i]) {
     73                 continue;
     74             }
     75             for(int j = first[i]; ~j; j = edge[j].next) {
     76                 int to = edge[j].to;
     77                 if(broke[to]) {
     78                     continue;
     79                 }
     80                 if(!same(to, i)) {
     81                     join(to, i);
     82                     tot --;
     83                 }
     84             }
     85         }
     86         stack<int>s;
     87         s.push(tot);
     88         for(int i = num; i >= 1; i -- ) {
     89             int x = hit[i];
     90             int cnt = 0;
     91             for(int j = first[x]; ~j; j = edge[j].next) {
     92                 int to = edge[j].to;
     93                 if(broke[to]) {
     94                     continue;
     95                 }
     96                 if(!same(x, to)) {
     97                     join(x, to);
     98                     cnt ++;
     99                 }
    100             }
    101             tot = tot - (cnt - 1);
    102             broke[x] = 0;
    103             s.push(tot);
    104         }
    105         while(!s.empty()) {
    106             printf("%d
    ", s.top());
    107             s.pop();
    108         }
    109     }
    110 
    111     return 0;
    112 }
  • 相关阅读:
    玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-4 模态弹出框--结构分析
    玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-3 模态弹出框
    玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-2 动画过渡
    玩转Bootstrap(JS插件篇)-第1章 模态弹出框 :1-1导入JavaScript插件
    SpringMVC中的 JSR 303 数据校验框架说明
    对JSON格式的城市按照拼音首字母排序
    Urozero Autumn 2016. BAPC 2016
    BZOJ2596 : [Wc2007]疯狂赛车
    BZOJ3253 : 改编
    XVII Open Cup named after E.V. Pankratiev. GP of Moscow Workshops
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/8749488.html
Copyright © 2020-2023  润新知