• hdu 3172 Virtual Friends(并查集)University of Waterloo Local Contest 2008.09


    题目比较简单,但作为长久不写题之后的热身题还是不错的。

    统计每组朋友的朋友圈的大小。

    如果a和b是朋友,这个朋友圈的大小为2,如果b和c也是朋友,那么a和c也是朋友,此时这个朋友圈的大小为3。

    输入t,表示接下来有t组数据。

    每组数据有n组朋友关系。

    接下来n行,每行一组朋友关系,然后输出这组朋友的朋友圈大小,即有多少朋友。

    然后又是t组数据……(这点好坑)重复上述输入,直到数据结束。

    因为最多有10^5个人,那么如果用线性字符串数组保存人名,肯定超时得不要不要的,所以要用map(每次操作时间复杂度为log2(n))。

    据说如果并查集不压缩也会爆。我没试,诸位可以试一下。

    废话说完,上代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 #include <map>
     6 #include <string>
     7 using namespace std;
     8 
     9 map<string, int> mp;                //字符串与数字转换
    10 int val[100010];                    //朋友数
    11 int mg[100010];                     //并查集使用的数组
    12 int n, t;
    13 
    14 int find(int x)
    15 {
    16     int fx = x;
    17     while(mg[fx] != fx) fx = mg[fx];
    18     while(mg[x] != x)
    19     {
    20         int mid = mg[x];
    21         mg[x] = fx;
    22         x = mid;
    23     }
    24     //printf("%5d
    ", fx);
    25     return fx;
    26 }
    27 
    28 void merge(int x, int y)
    29 {
    30     int mx = find(x);
    31     int my = find(y);
    32     if(mx != my)
    33     {
    34         val[mx] += val[my];
    35         val[my] = val[mx];
    36         mg[mx] = my;
    37 
    38     }
    39     printf("%d
    ", val[mx]);
    40 }
    41 
    42 int main()
    43 {
    44 //    freopen("test.txt", "r", stdin);
    45     while(~scanf("%d", &t))
    46     {
    47         while(t--)
    48         {
    49             scanf("%d", &n);
    50             for(int i = 0; i < 100010; i++)
    51             {
    52                 val[i] = 1;
    53                 mg[i] = i;
    54             }
    55             char a[25], b[25];
    56             int ans = 1;                            //因为map中int初始值为0,所以赋值时应从1开始
    57             mp.clear();                             //每次注意清空mp
    58             for(int i = 0; i < n; i++)
    59             {
    60                 scanf("%s%s", a, b);
    61                 if(!mp[a]) mp[a] = ans++;           //加入新节点
    62                 if(!mp[b]) mp[b] = ans++;
    63                 merge(mp[a], mp[b]);
    64             }
    65         }
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    【OI新闻】2016.10.06
    旧博客欢迎莅临
    【NYOJ42】一笔画问题
    LCIS最长公共上升子序列
    LIS最长上升子序列
    LCS最长公共子序列
    T2848 列车调度(二分或dp)
    二分图的最大匹配、完美匹配和匈牙利算法
    高精大水题
    最大0,1子矩阵
  • 原文地址:https://www.cnblogs.com/mypride/p/4650952.html
Copyright © 2020-2023  润新知