zoukankan      html  css  js  c++  java
  • 【并查集】BZOJ1370- [Baltic2003]Gang团伙

    【题目大意】

    在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1、 我朋友的朋友是我的朋友; 2、 我敌人的敌人是我的朋友; 所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?

    【思路】

    水………NOIP的小孩都不屑于玩……

    把i拆成i和i+n,其中i表示i的朋友,i+n表示i的敌人。对于(i,j):

    (1)i,j是朋友,那么合并i和j。

    (2)i,j不是朋友,那么合并i和j+n,j和i+n,代表敌人的敌人是我的朋友。

    *注意,如果i和j是敌人,那么它们的敌人不一定是朋友。所有不要合并i+n和j+n。

    好水啊……

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAXN=5000;
     7 int u[MAXN],h[MAXN],appear[MAXN];
     8 int n,m,gang;
     9 
    10 int find(int x)
    11 {
    12     int r=x,temp;
    13     while (u[r]!=r) r=u[r];
    14     while (x!=r)
    15     {
    16         temp=u[x];
    17         u[x]=r;
    18         x=temp;
    19     }
    20     return r;
    21 }
    22 
    23 void union_set(int fa,int fb)
    24 {
    25     if (h[fa]>=h[fb])
    26     {
    27         u[fb]=fa;
    28         if (h[fa]==h[fb]) h[fa]++;
    29     }
    30     else u[fa]=fb;
    31 }
    32 
    33 void init()
    34 {
    35     for (int i=1;i<=2*n;i++)
    36     {
    37         u[i]=i;
    38         h[i]=1;
    39     }
    40 }
    41 
    42 void solve()
    43 {
    44     scanf("%d%d",&n,&m);
    45     init();
    46     for (int i=1;i<=m;i++)
    47     {
    48         char op[2];
    49         int u,v;
    50         scanf("%s%d%d",op,&u,&v);
    51         if (op[0]=='F')
    52         {
    53             int fa=find(u),fb=find(v);
    54             if (fa!=fb) union_set(fa,fb);
    55         }
    56         else
    57         {
    58             int fa=find(u),fb=find(v+n);
    59             if (fa!=fb) union_set(fa,fb);
    60             fa=find(v),fb=find(u+n);
    61             if (fa!=fb) union_set(fa,fb);
    62         }
    63     }
    64 }
    65 
    66 void getans()
    67 {
    68     for (int i=1;i<=n;i++) u[i]=find(i);
    69     memset(appear,-1,sizeof(appear));
    70     gang=0;
    71     for (int i=1;i<=n;i++)
    72     {
    73         if (appear[u[i]]==-1)
    74         {
    75             gang++;
    76             appear[u[i]]=1;    
    77         }
    78     }
    79     printf("%d",gang);
    80 }
    81 
    82 int main()
    83 {
    84     solve();
    85     getans();
    86     return 0;
    87 }
  • 相关阅读:
    Java 抽象类
    Java 多态
    Java 重写与重载
    Java继承
    声卡驱动
    Sublime Text 3快捷键
    近年来世界各地ICO的花式骗局盘点
    区块链未能大爆发的影响因素有哪些?
    BCH分叉是一次站队博弈
    一文读懂百倍币的诞生背景
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5914545.html
Copyright © 2011-2022 走看看