您的位置:首页 > 编程语言 > C语言/C++

Cpp环境【Uva1160】【Vijos2806】易爆物

2016-07-15 11:33 239 查看
【问题描述】




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

【输入格式】


  包含多组数据。每组数据包含若干行,每行为两个不同的整数a,b,代表一个由元素a和元素b组成的简单化合物。所有简单化合物按照交给你的先后顺序排列。每组数据用一个-1结尾,然后是新的一组数据。

【输出格式】


  对于每组数据,输出没有装车的化合物的个数。

【输入样例】


1 2

3 4

3 5

3 1

2 3

4 1

2 6

6 5

-1

【输出样例】


3

【数据范围】


0<=a,b<=10^5

【来源】


uva 1160

【思路梳理】


看着就不想一个简单题的样子,按照一般思路来想的话会涉及到一个问题:需要使用一个容器存储输入进的元素,便于随时检查某个元素是否在这个容器中出现过(或者是能够很轻松地去重)并且能够很轻松的马上调用出这个容器内的元素个数。首选是“优先队列+binary_search”,每一次加入新的化合物就判断一次加上这两种化合物的元素后的总元素数量与化合物总数是否相等,根据判断的结果决定是否要将这两种元素加入。这个思路是可行的,但复杂度较高。

更好的解决方法是并查集。将每一个元素看作一个顶点,每一次加入新的化合物就像是将两个元素连上一条无向边。思考:那么什么时候不能放入这个化合物?答案是加入这个化合物后,元素种类数等于化合物总数时。映射到并查集来:什么时候不能向其中加入一条边?答案是加入这条边后,顶点数等于边数时。什么时候顶点数会等于边数?就是当一棵树加入了一条边后形成了一个环。该代码将在【Cpp代码】给出。

那么结果就不言而喻:我们只需要往空边图中不断地加边,如果某个时刻,等待被加入的边的两个顶点都在同一树内,那么这条边就不能够被加入。

注意一下输入问题!

需要扣的一个字眼问题:“如果车上存在k个简单化合物,正好包含k种元素,那么他们将组成一个易爆的混合物”,注意的是只要存在了包含k种元素的k种化合物就不能装车(即不一定是要所有的k个化合物中存在了k种元素)。也就是说“1-2 3-4 4-3”的简单化合物中,最后一个化合物“4-3”是不被允许装车的

【Cpp代码】

#include<cstdio>
#include<iostream>
#define maxn 100005
using namespace std;
int n,fa[maxn],ans=0,k=0,num=0;

int find(int x)
{
if(fa[x]==x)    return x;
int root =find(fa[x]);
fa[x]=root;
return root;
}

void Union(int x,int y)
{
fa[find(y)]=find(x);
}

bool judge(int x,int y)
{
return find(x)==find(y);
}

void initial()
{
for(int i=1;i<maxn;i++) fa[i]=i;
}

int main()
{
//freopen("in.txt","r",stdin);
int a,b;

while(scanf("%d",&a)==1)
{
initial();ans=0,k=0,num=0;
while(a!=-1)
{
scanf("%d",&b);
if(judge(a,b))  ans++;
else Union(a,b);
scanf("%d",&a);
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息