ZOJ 3789 Gears(并查集)
2014-11-05 21:49
477 查看
题意:有一些齿轮,旋转方向是确定的,有几个操作,一个是把2个齿轮合起来,当然必须是旋转方向相反的,一个是询问2个齿轮的旋转方向关系,一个是把一个齿轮拿走,这个地方理解好坑爹,因为旋转方向是固定的,所以删除这个齿轮,这个组里的其他齿轮还是在一起的因为都知道方向关系了。。还有一个是询问这个组有几个齿轮。
很容易就想到是并查集。不过还需要一个depth数组去维护跟根节点的关系,在查找根节点的时候直接更新depth数组,删除操作直接新建一个节点就可以了,这个地方跟今年多校一道军队排队换来换去的处理是一样的。
但是这个更新的时候要注意。如果是2个组里的子节点相连接,除了要把2个组的根节点相连接,depth数组到底应该怎么更新,我当时这里没有想明白看了下网上题解,发觉好多都是depth[x] = depth[y]+1,这样是不对的啊(虽然能AC但是找一个反例很容易),你只更新了一个子节点的,这个组的其他节点该怎么办???不变??事实上解决办法应该是更新那个要并过去的根节点的depth,这2个组相连的关键点是2个子节点,所以这个
根节点的depth应该等于depth[x]+dep[y]+1。这样的话这个组的其他节点查询的时候就会经过根节点一起更新了。
AC代码:
很容易就想到是并查集。不过还需要一个depth数组去维护跟根节点的关系,在查找根节点的时候直接更新depth数组,删除操作直接新建一个节点就可以了,这个地方跟今年多校一道军队排队换来换去的处理是一样的。
但是这个更新的时候要注意。如果是2个组里的子节点相连接,除了要把2个组的根节点相连接,depth数组到底应该怎么更新,我当时这里没有想明白看了下网上题解,发觉好多都是depth[x] = depth[y]+1,这样是不对的啊(虽然能AC但是找一个反例很容易),你只更新了一个子节点的,这个组的其他节点该怎么办???不变??事实上解决办法应该是更新那个要并过去的根节点的depth,这2个组相连的关键点是2个子节点,所以这个
根节点的depth应该等于depth[x]+dep[y]+1。这样的话这个组的其他节点查询的时候就会经过根节点一起更新了。
AC代码:
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<ctype.h> #include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdlib> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> #include<ctime> #include<string.h> #include<string> #include<sstream> #include<bitset> using namespace std; #define ll long long #define eps 1e-8 #define NMAX 200005 #define MOD 1000000009 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 template<class T> inline void scan_d(T &ret) { char c; int flag = 0; ret=0; while(((c=getchar())<'0'||c>'9')&&c!='-'); if(c == '-') { flag = 1; c = getchar(); } while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); if(flag) ret = -ret; } int fa[6*100000+10],newg[2*100000+10],depth[6*100000+10],si[6*100000+10]; int findit(int x) { if(fa[x] == x) return x; int t = findit(fa[x]); depth[x] += depth[fa[x]]; return fa[x] = t; } int main() { #ifdef GLQ freopen("input.txt","r",stdin); // freopen("o4.txt","w",stdout); #endif // GLQ int n,m,a,b; while(~scanf("%d%d\n",&n,&m)) { for(int i = 1; i <= n; i++) { fa[i] = newg[i] = i; si[i] = 1; depth[i] = 0; } char temp; while(m--) { temp = getchar(); if(temp == 'L') { scanf("%d%d\n",&a,&b); a = newg[a]; b = newg[b]; findit(a); findit(b); int ra = fa[a],rb = fa[b]; if(ra == rb) continue; si[rb] += si[ra]; depth[ra] = depth[a]+depth[b]+1; fa[ra] = rb; } if(temp == 'D') { scanf("%d\n",&a); int pp = newg[a]; findit(pp); si[fa[pp]]--; n++; newg[a] = n; depth = 0; si = 1; fa = n; } if(temp == 'Q') { scanf("%d%d\n",&a,&b); a = newg[a]; b = newg[b]; findit(a); findit(b); int ra = fa[a],rb = fa[b]; if(ra != rb) printf("Unknown\n"); else { int x = depth[a]%2,y = depth[b]%2; if(x == y) printf("Same\n"); else printf("Different\n"); } } if(temp == 'S') { scanf("%d\n",&a); a = newg[a]; findit(a); int ra = fa[a]; printf("%d\n",si[ra]); } } } return 0; }
相关文章推荐
- ZOJ 3789 - Gears (并查集)
- ZOJ 3789 Gears(并查集)
- 【并查集】 ZOJ 3789 Gears
- ZOJ 3789 Gears 并查集
- zoj 3789 并查集
- ZOJ_3789_Gears(可统计集合元素个数和可删除结点的带权并查集)
- zoj 3789 并查集
- ZOJ 3789 Gears
- ZOJ 3789 并查集
- ZOJ 3789 Gears (并查集 合并+删除+离根节点的距离)
- ZOJ 3789 齿轮操作 带权并查集
- zoj 3659 并查集
- ZOJ 3811 dfs&并查集
- ZOJ 3261 (并查集)
- ZOJ2334 Monkey King 并查集 STL
- zoj Conquer a New Region 并查集
- ZOJ1789(The Suspects)j简单并查集
- ZOJ 3811 Untrusted Patrol 并查集 染色 BFS
- ZOJ 3261 Connections in Galaxy War 【并查集 + 离线逆向处理】好题!!
- zoj 1789 The Suspects (并查集)