zoukankan      html  css  js  c++  java
  • FZU2155 盟国

    Problem Description 题目链接

    世界上存在着N个国家,简单起见,编号从0~N-1,假如a国和b国是盟国,b国和c国是盟国,那么a国和c国也是盟国。另外每个国家都有权宣布退盟(注意,退盟后还可以再结盟)。

    定义下面两个操作:

    “M X Y” :X国和Y国结盟

    “S X” :X国宣布退盟

     Input

    多组case。

    每组case输入一个N和M (1 ≤ N ≤ 100000 , 1 ≤ M ≤ 1000000),N是国家数,M是操作数。

    接下来输入M行操作

    当N=0,M=0时,结束输入

     Output

    对每组case输出最终有多少个联盟,格式见样例。

     Sample Input

    5 6
    M 0 1
    M 1 2
    M 1 3
    S 1
    M 1 2
    S 3
    3 1
    M 1 2
    0 0

     Sample Output

    Case #1: 3
    Case #2: 2
     
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    /*
        思路:并查集的操作 涉及到并查集的删除 用俩个数组存储
            使用虚根法,即每次指向根节点是未出现的过的,因此要保证数组开足够大
            其中real[i]=p,表示节点i所存放的位置在father[p],在father数组进行并查集的操作
            这样可以保证当i节点删除的时候,不会影响原来的节点树结构
    */
    
    const int N = 300003;
    int real[N];//存放i节点的真正位置
    int father[N];//用以并查集操作
    int visit[N];
    int t;//代表数组末尾未出现的点,用来删除操作存放
    
    //寻找祖先 并使用路径压缩 可以缩短并查集的查找时间
    int FindAncestor(int a)
    {
        if (father[a] == a)
            return a;
        return father[a] = FindAncestor(father[a]);
    }
    //并查集联合
    void Union(int a, int b)
    {
        int an = FindAncestor(real[a]);
        int bn = FindAncestor(real[b]);
        if (an != bn)
        {
            //连a即可
            father[bn] = an;
        }
    }
    
    //删除操作
    void del(int x)
    {
        //指向一个新的未使用的位置,不会影响原先树结构
        real[x] = t;
        father[t] = t++;
    }
    
    int main()
    {
        int N, M, ans = 1;
        while (scanf("%d%d", &N, &M), N || M)
        {
            t = N;
    
            for (int i = 0; i < N; i++)
            {
                real[i] = i;
                father[i] = i;
            }
    
            char a;
            int b, c;
            getchar();
            while (M--)
            {
                scanf("%c", &a);
                if (a == 'M')
                {
                    scanf("%d%d", &b, &c);
                    Union(b, c);
                }
                else
                {
                    scanf("%d", &b);
                    del(b);
                }
                getchar();
            }
            memset(visit, 0, sizeof(visit));
            int res = 0;
            for (int i = 0; i < N; i++)
            {
                //查找根  若根未使用过 联盟数+1
                int temp = FindAncestor(real[i]);
                if (!visit[temp])
                {
                    visit[temp] = 1;
                    res++;
                }
            }
            printf("Case #%d: %d
    ", ans++, res);
        }
        return 0;
    }

    参考链接:https://blog.csdn.net/a915800048/article/details/41703865

  • 相关阅读:
    ListView的item中EditText编辑(或者其他控件)修改本行数据
    C#:MVC引用Log4Net生成错误日志
    Web Developer教程
    EditPlus高级使用技巧(附视频、课件、代码下载)
    jQuery入门篇
    网摘系统架构
    BugFree 2.0使用帮助
    使用 WebDeployment Project 视频
    BugFreeHelper 2.2 For BugFree2.0(RTM)
    FireFox3推荐安装附加组件Top10(附官方主页和下载地址)
  • 原文地址:https://www.cnblogs.com/dlvguo/p/12718947.html
Copyright © 2011-2022 走看看