https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3601
题目大意:给你很多堆元素组合,每一堆组合有两个元素,当堆数等于元素种类数的时候,就会发生爆炸。你要把这些组合放到一个屋子里面,如果当前选择会发生爆炸,那么就拒绝,否则必须接受。输出拒绝的次数。
思路:这道题的转化还挺巧妙的,我们把每种元素看成一个点,如果这两个元素组合到了一起,我们就画上一条线。于是问题就转化成了:判断一个图是否有环。当两个结点的根结点相同时,再划线必定会有环,这是不合题意的。(题目说了不会有重复的组合出现)这个判断根结点是否相同的操作是不是就是并查集的操作呢~
#include<iostream>
#include<cstdio>
#include<stack>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<algorithm>
#include<iterator>
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
//转换成 图无环问题
const int MAX=100000;
int f[MAX+5];
int cnt=0;
void init()
{
for(int i=0;i<=MAX;i++)
f[i]=i;
cnt=0;
}
int father(int x)
{
return f[x]==x?x:f[x]=father(f[x]);
}
void Union(int x,int y)
{
int fx=father(x),fy=father(y);
if(fx==fy)
++cnt;
else
{
f[fx]=fy;
}
}
int main()
{
int n,m;
while(~scanf("%d",&n))
{
init();
while(n!=-1)
{
scanf("%d",&m);
Union(n,m);
scanf("%d",&n);
}
printf("%d\n",cnt);
}
return 0;
}