易爆物

易爆物D305

运行时间限制:1000ms; 运行空间限制:51200KB

试题描述

有一些简单化合物,每个化合物部由两种元素组成的(每个元素用一个大写字母表示)。你是一个装箱工人,从实验员那里按照顺序依次把一些简单化合物装到车上。但这里存在一个安全隐患:如果车上存在k个简单化合物,正好包含k种元素,那么它们将组成一个易爆的混合物。为了安全起见,每当你拿到一个化合物时,如果它和已装车的化合物形成易爆混合物,你就应当拒绝装车;否则就应该装车。编程输出有多少个没有装车的化合物。

输入

第一行包含一个正整数n,表示化合物的个数。接下来有n行,每行包括两个不同的整数a和b,表示一个由元素a和元素b组成的简单化合物。所有简单化合物按照交给你的先后顺序排列。

输出

一个数,表示没有装车的化合物的个数。

输入示例

6
2 4
3 4
2 9
3 8
4 8
3 9

输出示例

2

其他说明

数据范围:0 <= a,b <= 10^5
样例说明:化合物4 8和化合物3 9没有装车。

UVA1160

---------------------------------------------------------------------------------------------------------------------------------

讲解:

本题要求了装车顺序,这样这道题就变得so easy。

首先,题说的有点绕:“如果车上存在k个简单化合物,正好包含k种元素,那么它们将组成一个易爆的混合物。”这句话可能很多读者不明白,但这也是解题的思路:把每一个元素看成一个点,那么每一个简单化合物就是连接两个点的边。这样对于易爆物的定义就出来了。在一堆点中有许多遍连接两个点,当连接某一条边时,此图出现回路时这条边就不能连接(组成易爆物)。

这样,这道题就变成赤裸裸的并查集(元素是否在这个集合中)。

代码实现(如果看不懂(着急约会),跳过这个代码):

#include<iostream>

#include<cmath>

#include<cstring>

#include<algorithm>

#include<cstdio>

using namespace std;

struct union_find_set//并查集

{

         int father[100010],n;

         void create(int k)

         {

                   n=k;

                   for(int i=1;i<=n;i++) father[i]=i;

                   return;

         }//建立并查集,初始化

         int finds(int x)

         {

                   if(father[x]==x) return x;

                   return father[x]=finds(father[x]);//压缩路径

                   //return father[x]=father[x]==x?x:finds(father[x]);

                   //装逼专用

         }//寻找祖先

         bool unions(int x,int y)

         {

                   int t1=finds(x),t2=finds(y);

                   if(t1==t2) return false;

                   father[t2]=t1;

                   return true;

         }//合并

         /*int size()

         {

                   int ans=0,i;

                   for(i=1;i<=n;i++) if(father[i]==i) ans++;

                   return ans;

         }*/

         //查找集合的个数

         //本题不需要

};

int main()

{

         int i,x,y,n,ans=0;

         union_find_set f;

         scanf("%d",&n);

         f.create(100010);

         for(i=1;i<=n;i++)

         {

                   scanf("%d%d",&x,&y);

                   if(!f.unions(x,y)) ans++;//如果不装车,ans++

         }

         cout<<ans;

    return 0;

}
View Code

换一种编者喜欢的代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

using namespace std;

int n,ans,a,b,f[100005];

int gets(int x1)

{

    if(f[x1]==x1) return x1;

    f[x1]=gets(f[x1]);

    return f[x1];

}

void h(int x,int y)

{

    int f1=gets(x),f2=gets(y);

    if(f1==f2) ans++;

    else f[f1]=f2;

}

int main()

{

    int i;

    scanf("%d",&n);

    for(i=1;i<=100010;i++) f[i]=i;

    for(i=1;i<=n;i++) scanf("%d%d",&a,&b),h(a,b);

    printf("%d",ans);    

         return 0;

}
View Code

 

posted @ 2018-02-11 18:28  欢语_暗影  阅读(206)  评论(0)    收藏  举报