POJ 1182 食物链 分类并查集
2016-02-22 23:11
253 查看
点击打开链接
思路通过
通过将根分成3部分
应该也是属于分组并查集(种类并查集)。
对于这道题目,我们可以这样来理解,
建立3个集合A,B,C,
集合A表示和a是同一种类的元素,
集合B表示的是与 “a吃的元素” 是同一种类的元素,
集合C表示的是与 “吃a的元素” 是同一种类的元素。详细解释附在代码中。
三个集合{元素|1~3*n}其中对于任意一个集合,集合中元素(1~n)吃(n+1~2*n),(n+1~2*n)吃(2*n+1~3*n),(2*n+1~3*n)吃(1~n).
对于x和y 是同类.并且x和y不再一个结合的情况下,判断(y+n)、(y+2n)是否和x在一个集合,若都不是,那么(x,y)并成一个集合.(x+n,y+n)并成一个集合.(x+2*n,y+2*n)并成一个集合.
对于x 吃 y.如果x 和 (y+n)不再一个结合的情况下,判断 y、(y+2*n) 是否和 x 是在一个集合,若都不是,那么(x,y+n)并成一个集合.(x+n,y+2*n)并成一个集合.(x+2*n,y)并成一个集合.
思路通过
通过将根分成3部分
应该也是属于分组并查集(种类并查集)。
对于这道题目,我们可以这样来理解,
建立3个集合A,B,C,
集合A表示和a是同一种类的元素,
集合B表示的是与 “a吃的元素” 是同一种类的元素,
集合C表示的是与 “吃a的元素” 是同一种类的元素。详细解释附在代码中。
三个集合{元素|1~3*n}其中对于任意一个集合,集合中元素(1~n)吃(n+1~2*n),(n+1~2*n)吃(2*n+1~3*n),(2*n+1~3*n)吃(1~n).
对于x和y 是同类.并且x和y不再一个结合的情况下,判断(y+n)、(y+2n)是否和x在一个集合,若都不是,那么(x,y)并成一个集合.(x+n,y+n)并成一个集合.(x+2*n,y+2*n)并成一个集合.
对于x 吃 y.如果x 和 (y+n)不再一个结合的情况下,判断 y、(y+2*n) 是否和 x 是在一个集合,若都不是,那么(x,y+n)并成一个集合.(x+n,y+2*n)并成一个集合.(x+2*n,y)并成一个集合.
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #define LL long long using namespace std; int bin[160000]; int Find(int x) { return x==bin[x]?x:bin[x]=Find(bin[x]); } void Union(int x,int y) { int fx=Find(x); int fy=Find(y); if(fx!=fy) bin[fx]=fy; } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=3*n; i++) bin[i]=i; int num=0; for(int i=0; i<m; i++) { int d,x,y; scanf("%d%d%d",&d,&x,&y); if(x>n||y>n||x<1||y<1) { num++; continue; } if(d==1) { ///x吃y的关系 y吃x if(Find(x)==Find(y+n)||Find(x)==Find(y+2*n)) num++; else { ///建立同类的关系 Union(x,y); Union(x+n,y+n); Union(x+2*n,y+2*n); } } else { ///同类 y吃x if(Find(x)==Find(y)||Find(x)==Find(y+2*n)) num++; else { ///建立x吃y的关系 Union(x,y+n); Union(x+n,y+2*n); Union(x+2*n,y); } } } printf("%d\n",num); return 0; }