• C: City----逆向并查集


    C: City

    时间限制: 1 s      内存限制: 128 MB     
     

    题目描述

           如果城市A和城市B互通,城市B和城市C互通,那么城市A和城市C也互通,A、B、C三个城市算一个聚集点。先已知有n个城市和m条道路,想求的是有几个聚集点?但小S觉得太简单了,由于战争原因,某些城市会被导弹销毁掉,与之相应的道路也变得不可用。之前已经被销毁的不会被复原。现给定每次销毁的城市顺序,求每次销毁后聚集点有多少个。

    输入

    第一行输入n

    m,表示城市数量和道路数量(1n1041m2n)

    接下来m

    行,每行输入两个数aibi (1ai,bin)

    。表示ai和bi直接有道路

    m+2

    行输入q,表示有q个城市会被销毁 (1qn)

    接下来输入q

    个数,每行输入一个不重复的数,表示被销毁的城市

    输出

    输出一行q个数,每i个数表示第i个城市销毁后聚集点的数量

    样例输入

    8 9
    1 2
    1 3
    1 6
    2 4
    3 6
    4 5
    4 7
    5 7
    5 8
    4
    3 2 5 4
    

    样例输出

    1 2 3 3
     
    #include<iostream>
    #include<string.h>
    #include<math.h>
    #define ll long long
    using namespace std;
    int a[100005], b[100005], c[100005], p[100005], ans[100005], vis[100005], r[100005];
    int n, m, t = 0, cnt;
    void init()//初始化集合,每个元素的根节点都是自己
    {
        for (int i = 1; i <= n; i++)
        {
            p[i] = i;
        }
    }
    
    int find(int x)//查找元素x的根节点是谁
    {
        if (x == p[x])
            return x;
        else
            return p[x] = find(p[x]);
    }
    
    void join(int x, int y)//合并两个集合
    {
        int xRoot = find(x);
        int yRoot = find(y);
    
        if (xRoot == yRoot) //根节点相同,不合并
            return;
        if (r[xRoot] < r[yRoot]) //r[i]是元素i所在树的高度,矮树的根节点认高树的根节点做根节点
            p[xRoot] = yRoot;
        else if (r[xRoot] > r[yRoot])
            p[yRoot] = xRoot;
        else
        {
            p[yRoot] = xRoot;//树高相同,做根节点的树高度要加一
            r[xRoot]++;
        }
    }
    void num()//求不同子集个数
    {
        for (int i = 1; i <= n; i++)//有多少个p[i]==i,就有多少个子集
        {
            if (p[i] == i && vis[i] == 0)
                t++;
        }
    }
    bool sameRoot(int x, int y)//查询两个元素的老板是否相同
    {
        return find(x) == find(y);
    }
    int main()
    {
        scanf("%d%d", &n, &m);
    
        init();
        cnt = n;//当元素各不相连的时候,有n个集合
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d", &a[i], &b[i]);
        }
        int k;
        scanf("%d", &k);
        for (int i = 1; i <= k; i++)
        {
            scanf("%d", &c[i]);
            vis[c[i]] = 1;
        }
    
        for (int i = 1; i <= m; i++)
        {
            if (vis[a[i]] == 0 && vis[b[i]] == 0)
                join(a[i], b[i]);
        }
        num();
        int base = t;//销毁所有c[i]元素之后可以构成几个子集
        cnt = base;
        ans[k + 1] = base;
        for (int i = k; i >= 1; i--)
        {
            vis[c[i]] = 0;
            cnt = cnt + 1;
            ans[i] = cnt;
            for (int j = 1; j <= m; j++)
            {
                if (a[j] == c[i] && vis[b[j]] == 0)
                {
                    if (sameRoot(a[j], b[j]))
                        ans[i] = cnt;
                    else
                    {
                        join(a[j], b[j]);
                        {
                            cnt = cnt - 1;
                            ans[i] = cnt;
                        }
                    }
                }
                if (b[j] == c[i] && vis[a[j]] == 0)
                {
                    if (sameRoot(a[j], b[j]))
                        ans[i] = cnt;
    
                    else
                    {
                        join(a[j], b[j]);
                        {
                            cnt = cnt - 1;
                            ans[i] = cnt;
                        }
                    }
                }
    
            }
        }
        for (int i = 2; i <= k + 1; i++)
        {
            printf("%d", ans[i]);
            if (i != k + 1)
                printf(" ");
        }
        printf("
    ");
        //system("pause");
        return 0;
    }
    相似题目:https://www.cnblogs.com/-citywall123/p/10719924.html



  • 相关阅读:
    如何用vue-cli4.0构建多页面模板脚手架!?本文实战教你
    最新ES6+中数组的拓展总结,面试必备
    2020最新Vue项目性能优化实战,80%的人都不会
    vue 运行环境安装与配置
    css 文本缩进+间距+溢出
    vue 生成二维码+截图
    vue 缓存界面
    webpack 4 入坑及爬坑记录
    移动端页面使用单位的问题:关于px、百分比、em、rem开发中逐渐转换的问题记录
    基于vuejs和element-ui的表单验证——循环表单和循环表格验证
  • 原文地址:https://www.cnblogs.com/-citywall123/p/10729243.html
Copyright © 2020-2023  润新知