poj 1182
http://poj.org/problem?id=1182
一个利用并查集的经典题目。
思路:在网上看到别人的思路,觉得方法还是挺不错的。
首先,开辟一个3*n的数组belg,用来存b和c的关系,在belg[c+m]存,c是被谁吃的,belg[c+2*m]存b是吃谁的。
bool judge(int x,int y) {return (Find(x)==Find(y));}
如果judge(b,c+m)和 judge(b,c+2*m)都为假的话,那么可以说明,b和c是在同类。
然后合并b,c。b+m,c+m。b+2m,c+2m。
第一个judge可以判断,b不会吃c,第二个Judge可以判断c也不会吃b,所以,b,c肯定是同类。
如果judge(b,c)和judge(b,c+2*m)都为假的话,那么可以说明,c是被b吃的,然后合并b,c+m。b+m,c+2*m。b+*2m,c;
第一个judge可以判断b和c不是同一类,第二个judge可以判断c不会吃b,那么就可以说明c是被b吃的。c是被b吃的,那么说明,c+m存的就是b,所以c+m和b合并。之后的也是同样的意思。
1 #include <stdio.h> 2 #include <string.h> 3 4 5 int belg[150005]; 6 7 int Find(int x) //Find 的迭代写法。 8 { 9 int _x=x,_b; 10 while(_x!=belg[_x]) 11 { 12 _x=belg[_x]; 13 } 14 while(x!=belg[x]) 15 { 16 _b=belg[x]; 17 belg[x]=_x; 18 x=_b; 19 } 20 return _x; 21 } 22 23 bool judge(int x,int y) {return (Find(x)==Find(y));} 24 25 void unite(int x,int y) 26 { 27 int root1=Find(x); 28 int root2=Find(y); 29 if(root1!=root2) belg[root1]=root2; 30 } 31 32 int main() 33 { 34 int m,n,a,b,c,ans=0; 35 // freopen("in.txt","r",stdin); 36 scanf("%d%d",&m,&n); 37 for(int i=1;i<=m*3;i++) 38 belg[i]=i; 39 while(n--) 40 { 41 scanf("%d%d%d",&a,&b,&c); 42 if(b>m||c>m) ans++; 43 else if(a==1) 44 { 45 if(judge(b,c+m)||judge(b,c+2*m)) ans++; 46 else { //b,c是同类时,合并所有的信息。 47 unite(b,c); 48 unite(b+m,c+m); 49 unite(b+2*m,c+2*m); 50 } 51 } 52 else { 53 if(judge(b,c)||judge(b,c+2*m)) ans++; 54 else { //b,c不是同类时,合并那些是同类的信息。 55 unite(b,c+m); 56 unite(b+m,c+2*m); 57 unite(b+2*m,c); 58 } 59 } 60 } 61 printf("%d\n",ans); 62 return 0; 63 }