poj 1703 poj1182(并查集)
2014-08-04 20:57
253 查看
poj1703: 题目大意:有n个人分别属于两个团伙,两种操作 D a b表示a b不在同一团伙,A a b表示询问a b是否在同一团伙首先要对并查集的基本概念了解,fa[]代表每个元素的父亲是谁,rank[]数组代表的是树的深度,但是根据不同题意会有不同的意义,这个对理解题意很重要。
那么对与这道题,刚开始每个节点都是一棵树,各自的父亲是自己,后来合并,即每个犯罪人都是一个节点,两个人的关系就是一条线,从而逐渐形成一棵树。
这棵树的边相连的两个点是代表不是一个团伙。其实我理解的是深度相同的都属于同一门派,但是这里只有两个门派,所以根据敌人的敌人是朋友的原则,这里rank[]数组的处理就好理解了,所以深度只有0,1.(这种处理方式在下一题会有更好的解释)。
// //可以把每个人看做一个点 每个关系看做一条边,rank[]本来表示树的深度,在这里表示点之间的权值,两点之间每条线权值为1, // rank[]依然是深度,表示该点到根节点的深度,如果两个点在同一个集合,并且深度一样,那么就是同一个帮派。 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define maxn 100005 int n; int fa[maxn]; int rank[maxn]; void Init() //初始化 { for(int i=0;i<=n;i++) { fa[i]=i; rank[i]=0; } } int find(int x) { if(fa[x]!=x) { int father=find(fa[x]); rank[x]=(rank[x]+rank[fa[x]])%2; fa[x]=father; return fa[x]; } return x; } void Union(int x,int y)//合并两个集合 相当于加一条边 { int a=find(x); int b=find(y); //find 的时候依次更新rank[] fa[a]=b; rank[a]=(rank[x]+rank[y]+1)%2; } int main() { int cas; scanf("%d",&cas); while(cas--) { int m,a,b,i; char ch[3]; scanf("%d%d",&n,&m); Init(); for(i=1;i<=m;i++) { scanf("%s%d%d",ch,&a,&b); if(ch[0]=='D') { Union(a,b); } else { if(n==2)printf("In different gangs.\n"); else if(find(a)==find(b)) { if(rank[a]==rank[b]) printf("In the same gang.\n"); else printf("In different gangs.\n"); } else printf("Not sure yet.\n"); } } } return 0; }poj1182
题目大意:
食物链 关系有三种情况 rank[] 表示与父亲的关系 0 同类 1 吃父亲,2 被父亲吃
关于向量的问题,这里有牛人很好的说明。O(∩_∩)O哈哈~ 我也是站在巨巨的肩膀上\(^o^)/~
http://www.cnblogs.com/wuyiqi/archive/2011/08/24/come__in.html
另外这个题还WA了好多次,其一是要单组数据才能过,其二就是合并的时候父节点写反辣。。噗噗。。
//食物链 关系有三种情况 rank[] 表示与父亲的关系 0 同类 1 吃父亲,2 被父亲吃 // 应该是和上一道提一样的 但总觉得有些不明白的地方 //好多牛人啊。。向量 tx ty 分别为x y 与其的父亲的关系,已知 x->tx x->y y->ty // 求 tx->ty 因为两个合并时要fa[ty]=tx; // tx->ty = tx->x+x->y+y->ty // so:tx->ty=(-rank[x]+d-1+rank[y])%3;=(rank[y]-rank[x]+d-1)%3 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int n; int fa[55555]; int rank[55555]; void Init() { for(int i=1;i<=n;i++) { fa[i]=i; rank[i]=0; } } int find(int x) { if(fa[x]!=x) { int fath=find(fa[x]); rank[x]=(rank[x]+rank[fa[x]])%3; return fa[x]=fath; // 路径压缩 的时候rank[]如何修改呢? // fa[x]=ffa[x] x->tx tx->ttx so:x->ttx=(rank[x]+rank[fa[x]])%3; } return x; } int Union(int d,int x,int y) { if(x>n || y>n)return 1; if(d==1 && x==y)return 1; int tx=find(x); int ty=find(y); if(tx==ty) { if((rank[y]-rank[x]+3)%3!=d){return 1; } else return 0; } else { fa[ty]=tx; //这里不能写反了。。。 rank[ty]=(rank[x]-rank[y]+d+3)%3; return 0; } } int main() { // freopen("q.in","r",stdin); int k,d,x,y,res,i; scanf("%d%d",&n,&k)==2; res=0; Init(); for( i=1;i<=k;i++) { scanf("%d%d%d",&d,&x,&y); if(Union(d-1,x,y))res++; } cout<<res<<endl; }
相关文章推荐
- (POJ 1703) Find them, Catch them【典型并查集:判断在不同的集合】
- poj 1703 Find them, Catch them(并查集应用)
- poj 1703 Find them, Catch them(并查集)
- POJ1703--Find them, Catch them--并查集
- poj 1703(种类并查集)
- poj 1703 Find them, Catch them 带权并查集
- POJ 1703 Find them, Catch them【带种类的并查集】
- poj1703 Find them, Catch them——带权并查集
- poj 1703(并查集的边权向量关系)
- poj 1703 poj 2492 并查集 桥梁判AB组
- POJ 1703 Find them, Catch them[并查集]
- POJ 1703 (并查集)
- 并查集 示例 : poj 1703 [Find them, Catch them - 帮派之争]
- POJ 1703 Find them, Catch them 并查集的应用
- poj-1703(并查集) Parity game
- poj--1703--Find them, Catch them(并查集巧用)
- POJ-1703-Find them, Catch them-带权并查集
- Poj(1703),种类并查集
- POJ - 1703 Find them, Catch them(种类并查集)
- POJ1703 Find Them,Catch Them 种类并查集