【uva11987】带删除的并查集

题意:初始有N个集合,分别为 1 ,2 ,3 .....n。有三种操件
1 p q 合并元素p和q的集合
2 p q 把p元素移到q集合中
3 p 输出p元素集合的个数及全部元素的和。

题解:

并查集。只是并查集中并没有删除的操作。所以就需要将删除的这个点的影响降到0,也就是给删除的点申请一个新的id,以后都是用这个新的id来表示这个点,这样原来的那个集合里的点p就没意义,自然影响就为0。

就我写了debug那里比较坑。。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7
 8 typedef long long LL;
 9 const int N=10*100100;
10 int n,m,tot,id[N],fa[N],cnt[N];
11 LL sum[N];
12
13 int findfa(int x)
14 {
15     if(fa[x]==x) return x;
16     return findfa(fa[x]);
17 }
18
19 int main()
20 {
21     freopen("a.in","r",stdin);
22     freopen("a.out","w",stdout);
23     while(scanf("%d%d",&n,&m)!=EOF)
24     {
25         for(int i=1;i<=n;i++) id[i]=i,fa[i]=i,cnt[i]=1,sum[i]=i;
26         tot=n;
27         for(int i=1;i<=m;i++)
28         {
29             int tmp,x,y,xx,yy;
30             scanf("%d",&tmp);
31             if(tmp==1)
32             {
33                 scanf("%d%d",&x,&y);
34                 xx=findfa(id[x]);yy=findfa(id[y]);
35                 if(xx==yy) continue;//debug
36                 fa[xx]=yy;
37                 sum[yy]+=sum[xx];
38                 cnt[yy]+=cnt[xx];
39                 sum[xx]=0;cnt[xx]=0;
40             }
41             if(tmp==2)
42             {
43                 scanf("%d%d",&x,&y);
44                 xx=findfa(id[x]);yy=findfa(id[y]);
45                 tot++;
46                 id[x]=tot;
47                 fa[tot]=yy;
48                 sum[yy]+=(LL)x;
49                 cnt[yy]++;
50                 sum[xx]-=(LL)x;
51                 cnt[xx]--;
52             }
53             if(tmp==3)
54             {
55                 scanf("%d",&x);
56                 xx=findfa(id[x]);
57                 printf("%d %lld\n",cnt[xx],sum[xx]);
58             }
59             // for(int j=1;j<=n;j++)
60             // {
61                 // printf("%d fa = %d cnt = %d sum = %d\n",j,fa[id[j]],cnt[id[j]],sum[id[j]]);
62             // }
63             // printf("\n");
64         }
65     }
66
67     return 0;
68 }
时间: 2024-11-08 11:45:44

【uva11987】带删除的并查集的相关文章

UVA - 11987 Almost Union-Find(带删除的并查集)

Almost Union-Find Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem A Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement something simil

FZU - 2155 - 盟国 (带删除的并查集~~)

Problem 2155 盟国 Accept: 140    Submit: 464 Time Limit: 5000 mSec    Memory Limit : 32768 KB  Problem Description 世界上存在着N个国家,简单起见,编号从0~N-1,假如a国和b国是盟国,b国和c国是盟国,那么a国和c国也是盟国.另外每个国家都有权宣布退盟(注意,退盟后还可以再结盟). 定义下面两个操作: "M X Y" :X国和Y国结盟 "S X" :X国

Poj 1182种类(带权)并查集

题目链接 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44316 Accepted: 12934 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是

poj 1182 食物链 (带关系的并查集)

  食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44835 Accepted: 13069 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类.

带偏移量的并查集

//带偏移量的并查集≈并查集补集 //维护各点到父节点的距离 可用来分类 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int n,f[1001],d[1001]; int find(int x) { if(x==f[x])

[HDU 3712] Fiolki (带边权并查集+启发式合并)

[HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[i]克的第i种物质.吉丽需要执行一定的步骤来配置药水,第i个步骤是将第a[i]个瓶子内的所有液体倒入第b[i]个瓶子,此后第a[i]个瓶子不会再被用到.瓶子的容量可以视作是无限的. 吉丽知道某几对液体物质在一起时会发生反应产生沉淀,具体反应是1克c[i]物质和1克d[i]物质生成2克沉淀,一直进行直

UVA11987 - Almost Union-Find (并查集带删除)

题目链接 题目大意:给出三个操作: 1 p q 表示将p q 这两个数所在的集合合并在一起.2 p q表示将p这个数从原有的集合中拿出来放到q所在的集合中.3 p表示查询p所在的集合总共有几个元素,和是多少. 解题思路:并查集.只是并查集中并没有删除的操作.所以就需要将删除的这个点的影响降到0,也就是给删除的点申请一个新的id,以后都是用这个新的id来表示这个点,这样原来的那个集合里的点p就没意义,自然影响就为0. 代码: #include <cstdio> #include <cstr

[POJ 1988] Cube Stacking (带值的并查集)

题目链接:http://poj.org/problem?id=1988 题目大意:给你N个方块,编号从1到N,有两种操作,第一种是M(x,y),意思是将x所在的堆放到y所在的堆上面. 第二种是C(x),意思是数x方块下面有多少个方块. 把两堆合成一堆,这个可以用并查集来实现,问题是,怎么样维护x方块下面有多少个方块呢? 先来分析一下题目,按照样例,我们有6个方块,1,2,3,4,5,6. 令Cnt(x) = C(x)+1. 先执行M(1,6),此时Cnt(1) = 2, Cnt(6) = 1 再

POJ 1703:Find them, Catch them(带权的并查集)

Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 30702   Accepted: 9447 Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon