zoukankan      html  css  js  c++  java
  • 团伙

    题目描述
    在某城市里住着n 个人,任何两个认识的人不是朋友就是敌人,而且满足:
    1、一个人的朋友的朋友是他的朋友。
    2、一个人敌人的敌人是他的朋友。
    3、一个人和他所有的朋友在同一个团伙。
    4、一个人的所有敌人是同一个团伙。
    告诉你关于这n 个人的m 条信息(即某两人是朋友,或者某两个人是敌人),请你计算出这个城市的人最多有多少个团伙。


    输入
    第一行:n(2<=n<=1000),m(1<=m<=5000),中间一个空格隔开。
    以下共m 行,每行的格式是:d x y,三个数中间一空格隔开,d=0:x 和y 是朋友,d=1:x和y 是敌人。


    输出
    N 个人最多组成了多少个团伙。


    样例输入
    6 4
    1 1 4
    0 3 5
    0 4 6
    1 1 2


    样例输出
    3


    提示
    5
    说明:{1}, {2, 4, 6}, {3, 5}共3 个团伙

    从题中的描述就可以判断出这是一道并查集题。

    首先,对于两人是朋友,就合并所在集合。对于两个人是敌人,比如a是b的敌人,那么就应该合并a和b的敌人所在的集合。同理,也要合并b和a的敌人所在的集合。

    那么可以开一个数组en[],en[i] = j 表示 i 的敌人是 j。那么若 i 和 j 是敌人,就应该合并 i 和en[j] 以及 j 和 en[i]。

    另一种表示敌人的方法是 i + n。就是合并 i 和 j + n 以及 j 和 i + n。

    给出第一个方法的代码

     1 #include<cstdio>
     2 #include<iostream> 
     3 #include<cstring> 
     4 #include<cmath>
     5 #include<algorithm> 
     6 using namespace std;
     7 const int maxn = 1e4 + 5;
     8 int p[maxn], en[maxn];
     9 int n, m, ans = 0;
    10 void init()
    11 {
    12     for(int i = 0; i < maxn; ++i) {p[i] = i; en[i] = 0;}
    13 }
    14 int Find(int x)
    15 {
    16     return p[x] == x ? x : p[x] = Find(p[x]);
    17 }
    18 void merge(int x, int y)
    19 {
    20     int px = Find(x), py = Find(y);
    21     if(px == py) return;
    22     else {p[px] = py; return;}
    23 }
    24 int main()
    25 {
    26     freopen("group.in", "r", stdin);
    27     freopen("group.out", "w", stdout);
    28     init();
    29     scanf("%d%d", &n, &m);
    30     for(int i = 1; i <= m; ++i)
    31     {
    32         int d, a, b; scanf("%d%d%d", &d, &a, &b);
    33         if(!d) merge(a, b);
    34         else                        
    35         {
    36             if(!en[a]) en[a] = b;        //a还没有敌人,就将b作为a的敌人所在集合的代表元素 
    37             else merge(b, en[a]); 
    38             if(!en[b]) en[b] = a;
    39             else merge(a, en[b]);         
    40         }
    41     }
    42     for(int i = 1; i <= n; ++i) if(p[i] == i) ans++;
    43     printf("%d
    ", ans);
    44 }
  • 相关阅读:
    codeforces 169 div2 C
    poj 1062(最短路)
    sgu 118
    sgu 101
    poj 2446二分图匹配
    ural 1129 (求数据)
    C#中抽象类和接口的区别(转)
    在.net(C# or vb.net)中,Appplication.Exit 还是 Form.Close有什么不同?
    一道爱出的题目,就是前面两个数相加 用递归方法实现
    C#冒泡排序
  • 原文地址:https://www.cnblogs.com/mrclr/p/8894054.html
Copyright © 2011-2022 走看看