并查集,动态连通性

http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2079&pid=1

n,m代码n个点,m条边

随之而来m条边

q 代表q个操作

q行,每行一个序号,代表将第m个输入的边删除,问删除后有多少个连通块。

思路:我们将m条边,和q询问记录下来,并将要删除的边标记。

然后对那些不用的边使用并查集,并算出有多少个连通块。

然后从最后一个询问开始,依次将那些边加入并查集,如果加入时,两个点的父亲不同,那么连通块就减少一个

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;
16 const int INF = 1 << 30;
17 const int N = 100000 + 10;
18 int u[N], v[N], q[N];
19 int father[N];
20 int ans[N];
21 bool vis[N];
22 void init(int n)
23 {
24     for (int i = 0; i <= n; ++i)
25         father[i] = i;
26     memset(vis, 0, sizeof(vis));
27 }
28 int find(int x)
29 {
30     if (x == father[x])
31         return x;
32     return father[x] = find(father[x]);
33 }
34 int main()
35 {
36     int n, m, i, Q;
37     while (scanf("%d%d", &n, &m) != EOF)
38     {
39         init(n);
40         for (i = 1; i <= m; ++i)
41         {
42             scanf("%d%d", &u[i], &v[i]);
43         }
44         scanf("%d", &Q);
45         for (i = 0; i < Q; ++i)
46         {
47             scanf("%d", &q[i]);
48             vis[q[i]] = true;
49         }
50         for (i = 1; i <= m; ++i)
51         {
52             if (!vis[i])
53             {
54                 int rx = find(u[i]);
55                 int ry = find(v[i]);
56                 if (rx != ry)
57                     father[rx] = ry;
58             }
59         }
60         int tmp = 0;
61         for (i = 1; i <= n; ++i)
62         if (father[i] == i)//算出连通块
63             tmp++;
64         for (i = Q - 1; i >= 0; --i)//从后往前,加入那些要删除的边
65         {
66             int rx = find(u[q[i]]);
67             int ry = find(v[q[i]]);
68             ans[i] = tmp;//
69             if (rx != ry)
70             {
71                 father[rx] = ry;
72                 tmp--;
73             }
74
75         }
76         for (i = 0; i < Q; ++i)
77             i == Q - 1 ? printf("%d\n", ans[i]) : printf("%d ", ans[i]);
78     }
79 }

时间: 2024-12-23 04:07:45

并查集,动态连通性的相关文章

nyoj 单词拼接(并查集判断连通性+欧拉路径)

这题还是比较难的. 首先建图方面,如果单纯的把单词作为点,能拼接的关系作为边,那么就是哈密顿图(每个点仅能走一次),难度比较大. 换一种思路,就是把每个单词看成一条有向边,由该单词的首字母指向尾字母. 那么这题便是欧拉图的问题了. 本质上采用的还是搜索,但是为了快速得到字典序最小的欧拉路径,首先要对单词集进行排序. 排完序后,用边集数组存图:再通过计算各点的出度与入度,同时判断基图(不考虑边的方向的图)的连通性,判断是否存在欧拉回路或欧拉通路. 如果存在欧拉回路,那么就从0开始搜索: 如果存在欧

[USACO18JAN] MooTube (并查集 -&gt; 维护连通性)

题目大意:给你一棵边权树,定义两点间距离为它们唯一路径上的最小路权,求与某点距离不大于K(k为已知)的点的数量 带权并查集维护集合内元素总数 路和问题 都按权值大到小排序,枚举问题, 建权值不小于K的边,并查集维护连通性,求集合元素内总数即可 1 #include <bits/stdc++.h> 2 #define N 200100 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 6 int n,q,cnt; 7 int fa[N],f[N]

hdu 5424 回溯+并查集判断连通性

题意:给定一个n个点n条边的无向图,判断是否存在哈密顿路径. 思路:先用并查集判断图是否连通,然后从度数最小的点开始回溯,看是否能找到一条哈密顿路径. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <set> 5 using namespace std; 6 7 const int INF = 999999; 8 const int N = 1001; 9

逆向思维 + 用并查集动态维护连通块的个数——Luogu P1197题解

题目大意: 给你一个 $ n $ 个点的图与 $ m $ 条边,接下来给出一个长度为 $ k $ 个整数,按照给出整数的顺序依次删掉对应编号的点,求出一开始的连通块的个数与接下来每次删除一个点后的连通块的个数.(连通块就是一个点集,这个集合里面的任意两个点都可以互相到达) 思路: 大体思路: 这个题目如果正向考虑会很难做,因为我们要每次维护一个不断删点的图的连通块个数是很难弄的.所以我们要倒着考虑.假如我们把删点的过程倒着考虑,就变成了从最后一个点往前添加进这个图里面的过程.所以这样问题就变成了

【板+并查集判断连通性】并查集判断连通性

1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 10 using namespace std; 11 typedef long long ll;

bzoj 4423 [AMPPZ2013]Bytehattan(对偶图,并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4423 [题意] 给定一个平面图,随时删边,并询问删边后两点是否连通.强制在线. [科普] 设有平面图G=(V,E),满足下列条件的图G'= (V',E') 称为图G的对偶图:G的任一面Ri内有且仅有一点Vi':对G的域Ri和Rj的共同边界Ek,画一条边Ek'=(Vi',Vj')且只与Ek交于一点:若Ek完全处于Ri中,则Vi'有一自环Ek',如下图G'是G的对偶图: From her

HDU 1878 欧拉回路 (并查集+欧拉回路)

题目地址:HDU 1878 这个题要注意欧拉回路与欧拉通路的区别.在都保证连通性的前提下,欧拉回路要求每个点的度数都是偶数,而欧拉通路允许两个点的度数是奇数.所以这题用并查集判断连通性后判断下度数就可以了. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib

BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

题目链接:http://uoj.ac/problem/274 题意概述: 没什么好概述的......概述了题意就知道怎么做了...... 分析: 就是用lct维护最大生成树. 然后如果去UOJ上面交发现如果不用并查集判断连通性就要T?! 然后我就默默改了并查集...(hash表并查集输入输出占据了一半的行数?!) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdl

[并查集]JZOJ 5794 旅行

Description 悠悠岁月,不知不觉,距那传说中的pppfish晋级泡泡帝已是过 去数十年.数十年 中,这颗泡泡树上,也是再度变得精彩,各种泡泡 天才辈出,惊艳世人,然而,似乎 不论后人如何的出彩,在他们的头 顶之上,依然是有着一道身影而立. 泡泡帝,pppfish. 现在,pppfish即将带着被自己收服的无数个泡泡怪前往下一个 空间,而在前往下 一个空间的道路上,有N个中转站,和M条空间虫洞连接中转站(双向通道,可有重 边,可有环),然而,通过虫洞 是要一定的条件的,pppfish将手

[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克沉淀,一直进行直