poj-1703 Find them, Catch them ***
2011-09-02 13:25
399 查看
【转】
解析:并查集的题目,并查集的拓展。一般的思路是先初始化,各个数自成一个组,然后是两个gangs自成一个组,但由于两个给定元素有三种关系: In
the same gang; In
different gangs; Not
sure
yet;
采用此模型的缺点是判断两个元素关系还未确定这种情况比较复杂,故模型需要改进。本题的正确模型是将已经确定关系的元素组成一个集合,然后利用两个元素的
father是同一个来确定这两个元素之间的关系。father[a]中存放的是a的根结点,rank中存放的是father[a]与a的关系,0表示两
者不在同一个gangs中,1表示两者在同一个gangs中。具体的程序还是沿袭了并查集的Make_Set()、Find_Set()、
Union_Set()的三步骤。
心得:并查集有三步是必须的:Make_Set()、Find_Set()、Union_Set()。
rank[a]的改变是伴随着father[a]的改变而更新的(有father改变就有rank改变),要是father改变了,而rank未改变,此时的rank就记录了一个错误的值,father未改变(即使实际的father已不是现在的值,但只要father未改变,rank
的值就是“正确”的,认识到这点很重要。),第一次错误就是因为没有考虑清楚这点。
解析:并查集的题目,并查集的拓展。一般的思路是先初始化,各个数自成一个组,然后是两个gangs自成一个组,但由于两个给定元素有三种关系: In
the same gang; In
different gangs; Not
sure
yet;
采用此模型的缺点是判断两个元素关系还未确定这种情况比较复杂,故模型需要改进。本题的正确模型是将已经确定关系的元素组成一个集合,然后利用两个元素的
father是同一个来确定这两个元素之间的关系。father[a]中存放的是a的根结点,rank中存放的是father[a]与a的关系,0表示两
者不在同一个gangs中,1表示两者在同一个gangs中。具体的程序还是沿袭了并查集的Make_Set()、Find_Set()、
Union_Set()的三步骤。
心得:并查集有三步是必须的:Make_Set()、Find_Set()、Union_Set()。
rank[a]的改变是伴随着father[a]的改变而更新的(有father改变就有rank改变),要是father改变了,而rank未改变,此时的rank就记录了一个错误的值,father未改变(即使实际的father已不是现在的值,但只要father未改变,rank
的值就是“正确”的,认识到这点很重要。),第一次错误就是因为没有考虑清楚这点。
#include<iostream> #include<cstdio> using namespace std; int father[100000+10]; //表示x的根结点 int rank[100000+10]; void Make_Set(int n){ int i; for(i=1;i<=n;i++){ father[i] = i; rank[i] = 1; } } int Find_Set(int a){ if(a==father[a]) return a; else { int temp = father[a]; father[a] = Find_Set(father[a]); rank[a] = (rank[temp]+rank[a]+1)%2 ; //必须有,更新路径压缩之后a与根结点之间的关系; father改变,rank就必须要跟着改变 } return father[a]; } void Union_Set(int a,int b){ int fa,fb; fa = Find_Set(a); fb = Find_Set(b); if(fa!=fb){ father[fa] = fb; rank[fa] = (rank[a]+rank[b])%2 ; //fa结点以下的结点的rank不需要改 } } int main(){ //freopen("1in.txt","r",stdin); //freopen("1out.txt","w",stdout); int T,N,M; char ch; int a,b,fa,fb; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); Make_Set(N); int i; for(i=1;i<=M;i++){ getchar(); scanf("%c%d%d",&ch,&a,&b); if(ch=='A'){ if(Find_Set(a)==Find_Set(b)){ //在使用rank之前,已经在用Find_Set函数寻找a的时候将a路径上的所有结点的rank值改变过了 if((rank[a]+rank[b])%2==0){ printf("In the same gang.\n"); } else printf("In different gangs.\n"); } else{ printf("Not sure yet.\n"); } } else{ Union_Set(a,b); } } } return 0; }
相关文章推荐
- 刷题——Find them, Catch them POJ - 1703
- Find them, Catch them poj 1703
- 【poj 1703 Find them, Catch them + 并查集】
- poj-1703 find them,catch them!
- POJ 1703 Find them, Catch them .
- Find them, Catch them POJ - 1703(并查集,模板)
- POJ1703 Find them, Catch them
- Find them, Catch them POJ - 1703
- poj-1703 Find them, Catch them!! 并查集
- POJ 1703 Find them, Catch them
- poj 1703 Find them,Catch them
- Find them, Catch them poj 1703
- POJ 1703 Find them, Catch them
- poj1703 Find them, Catch them——带权并查集
- Find them, Catch them POJ - 1703
- POJ1703 Find them, Catch them
- POJ 1703 Find themCatch them
- POJ 1703 Find them, Catch them
- 北大ACM1703——Find them, Catch them~~并查集
- poj1703 Find them Catch them