zoukankan      html  css  js  c++  java
  • Codeforces292D(SummerTrainingDay06-L 前缀并查集)

    D. Connected Components

    time limit per test:2 seconds
    memory limit per test:256 megabytes
    input:standard input
    output:standard output

    We already know of the large corporation where Polycarpus works as a system administrator. The computer network there consists of n computers and m cables that connect some pairs of computers. In other words, the computer network can be represented as some non-directed graph with n nodes and m edges. Let's index the computers with integers from 1 to n, let's index the cables with integers from 1 to m.

    Polycarpus was given an important task — check the reliability of his company's network. For that Polycarpus decided to carry out a series of k experiments on the computer network, where the i-th experiment goes as follows:

    1. Temporarily disconnect the cables with indexes from li to ri, inclusive (the other cables remain connected).
    2. Count the number of connected components in the graph that is defining the computer network at that moment.
    3. Re-connect the disconnected cables with indexes from li to ri (that is, restore the initial network).

    Help Polycarpus carry out all experiments and for each print the number of connected components in the graph that defines the computer network through the given experiment. Isolated vertex should be counted as single component.

    Input

    The first line contains two space-separated integers nm (2 ≤ n ≤ 500; 1 ≤ m ≤ 104) — the number of computers and the number of cables, correspondingly.

    The following m lines contain the cables' description. The i-th line contains space-separated pair of integers xiyi(1 ≤ xi, yi ≤ nxi ≠ yi) — the numbers of the computers that are connected by the i-th cable. Note that a pair of computers can be connected by multiple cables.

    The next line contains integer k (1 ≤ k ≤ 2·104) — the number of experiments. Next k lines contain the experiments' descriptions. The i-th line contains space-separated integers liri (1 ≤ li ≤ ri ≤ m) — the numbers of the cables that Polycarpus disconnects during the i-th experiment.

    Output

    Print k numbers, the i-th number represents the number of connected components of the graph that defines the computer network during the i-th experiment.

    Examples

    input

    6 5
    1 2
    5 4
    2 3
    3 1
    3 6
    6
    1 3
    2 5
    1 5
    5 5
    2 4
    3 3

    output

    4
    5
    6
    3
    4
    2

    题意:给出n(<=500)个点和m(<=1e4)条边,形成一个图,查询k(<=1e4)次,对于每个查询,有l和r,输出删除编号[l,r]区间内的边后形成的连通块的个数。

    思路:连通块肯定想到用并查集去维护。然后看到n比较小,所以可能可以每次查询里面复杂度带有n。

       因为删边用并查集不是很好维护,所以我们可能要想到能不能避免边的删除,那么很容易的想到前缀和思想。

       用dsu1[l]来保存[1,l]前l条边组成的图里面的并查集父节点的情况;

       用dsu2[r]来保存[r,n]后r条边组成的图里面的并查集父节点的情况;

       那么对于每一次查询[l,r]我只要把dsu1[l-1]和dsu2[r+1]的并查集父节点情况再次合并,也就是把两个并查集数组合并,那么就能得到新的并查集,这就是此刻图的情况了。

     1 //=============================================//
     2 //                   _ooOoo_                   //
     3 //                  o8888888o                  //
     4 //                  88" . "88                  //
     5 //                  (| -_- |)                  //
     6 //                   O = /O                   //
     7 //               ____/`---'\____               //
     8 //                .' \| |// `.                //
     9 //              / \||| : |||//               //
    10 //            / _||||| -:- |||||-             //
    11 //            | | | \ - /// | | |            //
    12 //            | \_| ''---/'' | / |            //
    13 //              .-\__ `-` ___/-. /            //
    14 //          ___`. .' /--.-- `. . __           //
    15 //       ."" '< `.___\_<|>_/___.' >'"".        //
    16 //      | | : `- \`.;` _ /`;.`/ - `: | |      //
    17 //          `-. \_ __ /__ _/ .-` / /        //
    18 //======`-.____`-.___\_____/___.-`____.-'======//
    19 //                   `=---='                   //
    20 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//
    21 //               佛祖保佑 永无BUG                //
    22 //     本模块已经经过开光处理,绝无可能再产生bug     //
    23 //=============================================//
    24 //2017-09-05
    25 #include <cstdio>
    26 #include <cstring>
    27 #include <iostream>
    28 #include <algorithm>
    29 
    30 using namespace std;
    31 
    32 const int N = 520;
    33 const int M = 11000;
    34 
    35 int n, m;
    36 struct DSU{
    37     int fa[N];
    38     void init(){
    39         for(int i = 0; i < N; i++)
    40           fa[i] = i;
    41     }
    42     int getfa(int x){
    43         if(x == fa[x])return x;
    44         return fa[x] = getfa(fa[x]);
    45     }
    46     void merge(int a, int b){
    47         int af = getfa(a);
    48         int bf = getfa(b);
    49         if(af != bf){
    50             fa[bf] = af;
    51         }
    52     }
    53 }dsu1[M], dsu2[M];//dsu1[i]表示由前i条边生成的并查集,dsu2[i]表示由后i条边生成的并查集
    54 
    55 int work(DSU ldsu, DSU rdsu){
    56     //将两棵并查集合并
    57     for(int i = 1; i <= n; i++)
    58           ldsu.merge(i, rdsu.getfa(i));
    59     int ans = 0;
    60     for(int i = 1; i <= n; i++)
    61           if(ldsu.fa[i] == i)
    62               ans++;
    63     return ans;
    64 }
    65 pair<int, int> line[M];
    66 int main()
    67 {
    68     std::ios::sync_with_stdio(false);
    69     cin.tie(0);
    70     //freopen("inputL.txt", "r", stdin);
    71     while(cin>>n>>m){
    72         for(int i = 1; i <= m; i++)
    73             cin>>line[i].first>>line[i].second;
    74         dsu1[0].init();
    75         for(int i = 1; i <= m; i++){
    76             dsu1[i] = dsu1[i-1];
    77             dsu1[i].merge(line[i].first, line[i].second);
    78         }
    79         dsu2[m+1].init();
    80         for(int i = m; i >= 1; i--){
    81             dsu2[i] = dsu2[i+1];
    82             dsu2[i].merge(line[i].first, line[i].second);
    83         }
    84         int  k, l, r;
    85         cin>>k;
    86         while(k--){
    87             cin>>l>>r;
    88             cout<<work(dsu1[l-1], dsu2[r+1])<<endl;
    89         }
    90     }
    91 
    92     return 0;
    93 }

     
  • 相关阅读:
    访问者模式
    oracle触发器简单实用示例
    C#控件交互效果类(也可以用作缩小面板放大,展示更多信息)
    23种设计模式探索C#
    windows快捷操作个人记录(常用)
    C#巧妙使用关键字async/await
    学习的枚举类型,结构以及初步了解数组
    目前学习.net时间让我摸不着头脑的事情
    对C#中几个循环语句的使用,请教
    学习了用控制台显示结果
  • 原文地址:https://www.cnblogs.com/Penn000/p/7482016.html
Copyright © 2011-2022 走看看