zoukankan      html  css  js  c++  java
  • 并查集初步题目(2)

    • vector和邻接表
    • 并查集的一个很风骚的技巧

    一. vector数组操作

    包含vector头文件

    声明:vector<type> name;

    方法:

    1. 加入一个元素至最后:vec.push_back(val);
    2. 清空数组中的所有元素:vec.clear();
    3. 访问其中元素:vec.at(i);
    4. vector中元素的个数:vec.size();
    5. 指定当前vector内元素个数:vec.resize(n); 会保留前n个元素。

    邻接表是一种储存图的方式,通常使用链表或者vector可变长数组实现。由表头节点表节点组成,图中的每一个顶点都在邻接表中为一个表头节点

    邻接表与普通数组储存图的好处在于节约了空间与时间。

    如果要遍历一个N个节点的图,数组需要两层for每层N次,事实上一个点并不一定与其它所有点都相邻,进行了无用的判断,还耗费了空间。

    如果使用邻接表,使用vector类,可以使速度加快,空间变小,邻接表只储存于表头节点相邻的顶点,因此少了不必要的空间和遍历。

    题目:

    Hungar个人很喜欢曹操这个人,所以这次有机会穿越到三国时代,他想帮助曹操打赢赤壁之战。 
    但是他去晚了,当他穿越到那的时候发现大火已经在蔓延了,所以他能做的就是马上告诉曹操把已经着火的船的锁链(船与船相连都是靠锁链达到的)给破坏掉使火不会蔓延到附近的船只。 

    现在告诉你曹操一共有N艘船,M条铁链,船只编号从0开始到n-1。 
    然后再告诉你依次着火的船只编号,问舍弃那艘船以后,剩下的船只能形成几个连通块(只要是被铁链连在一起的全部船只,就算一共连通块)。 
    船与船之间可能存在多条锁链。 

    Input

    输入包括第一行两个整数,N(1 <= N <= 2M)和M(1 <= M <= 200,000)。 
    接下来M行,每行包括两个整数x和y(x != y),分别表示编号为x和y的船只被一根锁链连起来。 
    再接下来一个正整数T表示着火船只的数量。 
    接下来T行,每行包含一个整数z表示被烧船只的编号,编号不会出现一样的,也就是说已经被烧的船只不会再去烧它。 

    Output

    输出z+1个数,第一行为着火前这些船的连通块数,后z行表示每次依次烧掉一只船后,剩下的连通块数。 

    Sample Input

    8 13
    0 1
    1 6
    6 5
    5 0
    0 6
    1 2
    2 3
    3 4
    4 5
    7 1
    7 2
    7 6
    3 6
    5
    1
    6
    3
    5
    7
    

    Sample Output

    1
    1
    1
    2
    3
    3

    由于题目中顶点的数量高达400000,所以使用邻接表储存图,然而题目要求的操作是每次去掉一个顶点,判断一次联通块数量,可以每次都去掉一个点,进行一次图遍历。复杂度太高,舍弃。技巧:反向操作,从一个已有的并查集中去除一个点非常难,但是加入一个点很简单,倒序将点加入,每次遍历加入的顶点的邻接表。最后倒序输出即为答案。
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #define MAX 400010
    using namespace std;
    
    vector<int> vis[MAX];
    int ans[MAX];
    int rec[MAX];
    bool node[MAX];
    int fa[MAX];
    int N,M;
    
    int find(int x)
    {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    void init()
    {
        memset(node,0,MAX * sizeof(bool));
        for (int i = 0; i < N; ++i) fa[i] = i;
        for(int i = 1 ; i <= MAX ; i++) vis[i].clear();
        
        return ;
    
    }
    
    
    int main()
    {
        while(~scanf("%d%d",&N,&M))
        {
    
            init();
            int a , b;
            for (int i = 1; i <= M ; ++i)
            {
                scanf("%d%d",&a,&b);
                vis[a].push_back(b);
                vis[b].push_back(a);
                
            }
            ///////////////////////////////////
            int case_num;
            scanf("%d",&case_num);
            int nodenum = N;
            for (int i = case_num - 1; i >= 0; i--)
            {
                scanf("%d",&rec[i]);
                node[rec[i]] = 1;
                nodenum--;
            }
            int key = 0;
            ans[key] = nodenum;
            /////////////////////////
            for (int i = 0; i < N; ++i)
            {
                a = i;
                for (int j = 0; j < vis[a].size(); ++j)
                {
                    b = vis[a].at(j);
                    if(node[a] || node[b]) continue;
                    if(find(a) != find(b)) {find(a) < find(b) ? fa[find(b)] = find(a) : fa[find(a)] = find(b);ans[key]--;}
                }
            }
    
            ///////////////////////
            
            for (int i = 0; i < case_num; ++i)
            {
                 key++;
                 ans[key] = ans[key - 1] + 1;
                 int a = rec[i];
                 node[a] = 0;
                 for (int j = 0; j < vis[a].size(); ++j)
                 {
                     b = vis[a].at(j);
                     if(node[a] || node[b]) continue;
                     if(find(a) != find(b)) { find(a) < find(b) ? fa[find(b)] = find(a) : fa[find(a)] = find(b); ans[key]--;}
                 }
            }
            for(int i = case_num ; i >= 0 ; i--)
                cout << ans[i] <<endl;
    
    
        }
        
        
    
    
        return 0;
    
    }
    
    
    
     
     
  • 相关阅读:
    golang1.8
    用jmeter测试mogonDd数据库
    Memcache课程
    appium 处理滑动的方法
    【MVC 2】MVC+EF框架结构实例:注册ID号验证
    【Ajax 3】JavaScript封装Ajax
    【Ajax 2】封装Ajax的核心对象:XMLHttpRequest对象
    【Ajax 1】Ajax与传统Web开发的区别
    【软工7】软件工程中的文档
    【软考10】计算机网络基础知识拾遗
  • 原文地址:https://www.cnblogs.com/ticsmtc/p/4963121.html
Copyright © 2011-2022 走看看