CodeForces 745C Hongcow Builds A Nation 并查集

题意:

给了你n个城市 m条边 k个政府

每个政府管辖的区域内不能和其他政府的区域有相连

即政府之间不存在路径

问你在维护这种关系的同时

最多再加多少条边

思路:

先找出来每个联通块

再找出来没有归属的孤立的点

把他们都放到最大的联通块里

然后每个联通块之间的点两两连边是n*(n-1)/2条边

最后算出来的ans-m就好了

(看别人的博客学了一个max_element

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(a) cerr<<#a<<"=="<<a<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 typedef pair<int,int> pii;
 7
 8 const int maxn=1e5+10;
 9
10 int fa[maxn];
11
12 int fd(int i)
13 {//并查集
14     if(fa[i]==0) return i;
15     else return fa[i]=fd(fa[i]);
16 }
17
18 int main()
19 {
20     int n,m,k;
21     scanf("%d%d%d",&n,&m,&k);
22     vector<int>vis(n+1,0);
23     vector<int>gov(k,0),num(k,0);
24     for(int i=0;i<k;i++)
25     {
26         scanf("%d",&gov[i]);
27     }
28     for(int i=0;i<m;i++)
29     {
30         int x,y;
31         scanf("%d%d",&x,&y);
32         int fx=fd(x),fy=fd(y);
33         if(fx!=fy)
34         {//如果不相连的话 把两个点相连
35             fa[fx]=fy;
36         }
37
38     }
39     for(int i=1;i<=n;i++)
40     {//寻找每个节点所在联通块的大小
41         vis[fd(i)]++;
42     }
43     int rest=n;//初始化所有的点都剩下了
44     for(int i=0;i<k;i++)
45     {//最每个政府所在联通块大小进行记录
46         num[i]=vis[fd(gov[i])];
47         rest-=num[i];//减去已经记录过的点
48     }
49     //剩下的rest就是孤立的点的个数
50
51     ///新姿势 找出最大的联通块
52     auto mx=max_element(num.begin(),num.end());
53     ///max_element类似于kdtree模板中的nth_element
54
55     *mx+=rest;//把剩下的点放到最大的连通块中
56     int sum=0;
57     for(auto i:num)
58     {
59         sum+=i*(i-1)/2;
60     }
61     printf("%d\n",sum-m);
62     return 0;
63 }/*
64
65 3 3 1
66 2
67 1 2
68 1 3
69 2 3
70
71 */
时间: 2024-12-25 19:22:16

CodeForces 745C Hongcow Builds A Nation 并查集的相关文章

CodeForces - 744A Hongcow Builds A Nation

http://codeforces.com/problemset/problem/744/A 这是一道考察连通块的题(做之前, 连通块是什么都不清楚) Note:点的集合 任意两点都有可达的路径 可以用并查集做 在一个政府管辖下的点 作为一个集合 根节点就是这个政府 再者 贪心 : 要求做多可以添加的边数 做多一个集合 n个点 使它构成完全图 得到的边数为n*(n-1) / 2 那么最终表达式可以为n[1]*(n[1]-1) / 2 + n[2]*(n[2]-1) / 2 +....+ n[k]

CodeForces 776D The Door Problem【并查集】

CodeForces 776D The Door Problem[并查集]并查集 设 f 1--m 表示 开的情况 m+1--2*m 表示关的情况 对于每盏灯 如果他 是关的 则 x--y x+m--y+m 表示要同关 或者同开 如果他 是开的 则 x+m--y x--y+m 表示一个关 一个开如果一盏灯 的 x 连向 了 x+m 则表示是矛盾了 那么久是错误的 题意:给你n个门,和m组开关,每扇门都有两个开关控制,每个开关控制x扇门,如果选择了某组开关,则使这组开关里的每个开关控制的所有的门按

Codeforces Round #250 (Div. 1) B 并查集

坑!神坑!深坑!,WA了几十把,最终答案  (ans * 2)/(n * 1.0 * (n - 1)) 要是写成(ans * 2)/(n *(n - 1)*1.0)就是WA,不明白为啥,愤怒的我 全改成double就可以了,若前面变量用了int的 答案必须是前一种写法, 题目不是特别难,没啥思路画一画就有思路了,10^5的n去扫肯定是要超时的,那就想想一次性的10^5,发想通过m是可以的,建边,边权就是两端点中小的那个,然后对最终答案的种数进行分析,发现其实就是 每次你要连接的两块连通块的个数相

Codeforces 745C:Hongcow Builds A Nation(并查集)

http://codeforces.com/problemset/problem/744/A 题意:在一个图里面有n个点m条边,还有k个点是受限制的,即不能从一个受限制的点走到另外一个受限制的点(有路径相连),问在这样的图里面遵守这样的规则可以最多添加几条边. 思路:这种题之前在做强连通的时候很常见,于是就写了tarjan..醒来后发现不用这么复杂,直接用并查集就可以做了. 1.对于每一个连通块,最多可以加上n*(n-1)/2条边. 2.对于受限制的连通块,取出一个点数最多的,和不受限制的块相连

Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[],使得两个数组中最大的数尽量小 题解 按照偏序表,构造出从小到大的拓扑图 如何解决相等的数的偏序关系? 用并查集缩点后再进行拓扑排序 如何解决最大的数最小? 只需要使得同一层的数相同就行,可以一批处理栈中的元素,对于一批栈中的元素产生的新点,先放进一个容器里,然后等到这批栈清空了,再把这个容器中的点

codeforces 691D Swaps in Permutation(并查集)

题意: 给你一个长度为n的数列,然后给你m组数, 表示这两个数可以交换 然后让你给出字典序最大的数列 思路: 用并查集,可交换的数都是成组的,把同一并查集中的数加在根节点的vector后, 在一个并查集中的数,从大到输出就好了 /* *********************************************** Author :devil ************************************************ */ #include <cstdio>

CodeForces 698B Fix a Tree (并查集应用)

当时也是想到了并查集,但是有几个地方没有想清楚,所以就不知道怎么写了,比如说如何确定最优的问题.赛后看了一下别人的思路,才知道自己确实经验不足,思维也没跟上. 其实没有那么复杂,这个题目我们的操作只有三个 1.确定根节点.2.解环. 3连接子树. 如果题目中给出了一个或者多个根节点,我们任选一个即可,证明:假设有k个可行根节点,那么选择一个不动,改动k-1次,每种选择都是这样.但如果题目中没有可选根节点,就不可以随便去选了,首先明确这种情况一定存在了1个或者多个环,我们一定要从环中选取根节点,因

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可以利用这个性质 考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配 那么我们考虑把这个点点匹配的模型转化成点边匹配 我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了 而这个问题,我们显然可以用并查集来很好的解决 考虑

Codeforces.1051G.Distinctification(线段树合并 并查集)

题目链接 \(Description\) 给定\(n\)个数对\(A_i,B_i\).你可以进行任意次以下两种操作: 选择一个位置\(i\),令\(A_i=A_i+1\),花费\(B_i\).必须存在一个位置\(j\),满足\(A_i=A_j,\ i\neq j\),才可以进行. 选择一个位置\(i\),令\(A_i=A_i-1\),花费\(-B_i\).必须存在一个位置\(j\),满足\(A_i=A_j+1\),才可以进行. 你需要对于所有\(i\in[1,n]\),求使得\(A_1,A_2,