UVA 11987 Almost Unio-Find(削除操作付きで検索集)
Problem A
Almost Unio-Find
I hope you know the beautiful Unio-Find structure.In this proble,you're to implement something simiar,but not identical.
The data structure you need to write is also a collection of disject sets、supporting 3 operation:
Initially、the collection contains n sets:{1}、{2}、{3}、{n}
Input
The e e e e e are several test cases.Each test case begis with a ininininininininininininininintwo integers n and m(1<=n、m(=100,000)、the number of integers、and the number of commmands.Each of the nexxt m inininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininof input file does not exceed 5 MB.
Output
For each type-3 command the sum of elements.
Sample Input
Initially:{1}、{2}、{3}、{4}、{5}
Collection after operation 1 2:{1,2}、{3}、{4}、{5}
Collection after operation 2 3:{1,2}、{3,4}、{5}(we omit the empy set that is produced when taring out 3 from{3})
Collection after operation 1 3:{1,2}、{3,4,5}
Collection after operation 2 4:{1,2,4}、{3,5}
最初はN個の集合があって、それぞれ1,2,3…nです.体操は三つあります
1:p q結合要素pとqのセット
2:p qはp要素をqセットに移動します.
3:pはp要素セットの個数と全部の要素の和を出力します.
考え方:1、3のステップに対して、2つの配列を探して記録すればいいです.
2の削除ステップについては、pのルートを直接qに向けてはいけない.pがあるセットのルートであれば、他のノードに影響を与えるからである.
したがって、pというノードは、集合に対して「影響なし」であり、新たにノード表示pが元のセットから逸脱したことを示すことができるので、もう一つの配列ID[p]を開いてpノードの現在の番号を表します.
Almost Unio-Find
I hope you know the beautiful Unio-Find structure.In this proble,you're to implement something simiar,but not identical.
The data structure you need to write is also a collection of disject sets、supporting 3 operation:
1 p q
ユニオンthe sets containing p and q.If p and q are already in the same set,ignore this command.2 p q
Move p to the set containing q.If p and q are already in the same set,ignore this command3 p
Return the number of elemens and the sum of elements in the set containing p.Initially、the collection contains n sets:{1}、{2}、{3}、{n}
Input
The e e e e e are several test cases.Each test case begis with a ininininininininininininininintwo integers n and m(1<=n、m(=100,000)、the number of integers、and the number of commmands.Each of the nexxt m inininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininof input file does not exceed 5 MB.
Output
For each type-3 command the sum of elements.
Sample Input
5 7
1 1 2
2 3 4
1 3 5
3 4
2 4 1
3 4
3 3
Output for the Sample Input3 12
3 7
2 8
ExplanionInitially:{1}、{2}、{3}、{4}、{5}
Collection after operation 1 2:{1,2}、{3}、{4}、{5}
Collection after operation 2 3:{1,2}、{3,4}、{5}(we omit the empy set that is produced when taring out 3 from{3})
Collection after operation 1 3:{1,2}、{3,4,5}
Collection after operation 2 4:{1,2,4}、{3,5}
最初はN個の集合があって、それぞれ1,2,3…nです.体操は三つあります
1:p q結合要素pとqのセット
2:p qはp要素をqセットに移動します.
3:pはp要素セットの個数と全部の要素の和を出力します.
考え方:1、3のステップに対して、2つの配列を探して記録すればいいです.
2の削除ステップについては、pのルートを直接qに向けてはいけない.pがあるセットのルートであれば、他のノードに影響を与えるからである.
したがって、pというノードは、集合に対して「影響なし」であり、新たにノード表示pが元のセットから逸脱したことを示すことができるので、もう一つの配列ID[p]を開いてpノードの現在の番号を表します.
#include
#include
const int maxn = 200010;
int fa[maxn],cnt[maxn],id[maxn];// , , ( )
long long sum[maxn];//
int n,m,dep;
void init()
{
for(int i = 0; i <= n; i ++)
{
sum[i] = fa[i] = id[i] = i;
cnt[i] = 1;
}
dep = n;
}
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void unite(int x,int y)
{
int fx = find(x);
int fy = find(y);
fa[fx] = fy;
sum[fy] += sum[fx];
cnt[fy] += cnt[fx];
}
void move(int x)
{
int fx = find(id[x]); // id[x] x, x ,
sum[fx] -= x; // x
cnt[fx] --; //
id[x] = ++ dep;
sum[id[x]] = x;
cnt[id[x]] = 1;
fa[id[x]] = id[x];
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int op,x,y;
while (~scanf("%d%d",&n,&m))
{
init();
while(m--)
{
scanf("%d",&op);
if(op == 1)
{
scanf("%d%d",&x,&y);
if(find(id[x]) != find(id[y]))
unite(id[x],id[y]);
}
else if(op == 2)
{
scanf ("%d%d",&x,&y);
if(find(id[x])!= find (id[y]))
move(x),unite(id[x],id[y]);
}
else
{
scanf("%d",&x);
int fx = find(id[x]);
printf("%d %lld
",cnt[fx],sum[fx]);
}
}
}
return 0;
}