首页 > 其他分享 >Hongcow Builds A Nation 题解

Hongcow Builds A Nation 题解

时间:2024-12-17 22:19:51浏览次数:5  
标签:连通 特殊 Hongcow Builds 题解 合并 ljl maxn 个点

Hongcow Builds A Nation 题解

洛谷

Codeforces

题目描述

给定一张 \(n\) 个点,\(m\) 条边的无向图,有 \(k\) 个点是特殊点。

每个连通块中都得保证无重边、无自环,且最多只有一个特殊点。

求最多还能加多少条边,满足以上条件。

思路简述

首先考虑以下有 \(n\) 个点的完全图共有多少条边:

第一个点可以和剩下的 \(n-1\) 个点匹配,第二个点可以和 \(n-2\) 个点匹配……

\[(n-1)+(n-2)+\cdots +2+1 \\ =\frac{n \cdot(n-1)}{2} \\ =\frac{n^2-n}{2} \]

因为题目中提到了连通块这一关键词,立马联想到用并查集来实现。

假设连通块 \(x\) 与连通块 \(y\) 可以合并,那么显然需要满足以下条件:

  • 连通块 \(x\) 与连通块 \(y\) 合起来最多只有一个特殊点。

当我们将所有内部有特殊点的连通块都合并完后,考虑无特殊点的连通块。

可以开个变量 num 统计所有无特殊点的连通块的成员数量和。

很显然,将所有无特殊点的连通块全部与连通块内节点数量最多的连通块合并起来最优。

那么我们就可以开个变量表示连通块内节点数量的最大值。最后全部内部无特殊点的连通块合并入最大值即可。

答案怎么统计呢?

考虑枚举所有连通块。

如果当前连通块内部没有特殊点,直接加入 num。继续访问下一个。

若当前连通块不是目前最大连通块,则用公式(上文提及)加入答案。

如果当前连通块大于目前最大连通块:

设当前连通块成员数量为 \(x\),最大连通块成员数量为 \(maxn\)。

1、用目前最大连通块合并入当前连通块,答案加上 \(\frac{maxn^2-maxn}{2}\)。

2、更新。\(maxn\) 赋值为 \(x\)。

3、注意顺序不能反。

Code

//wrote by Atserckcn
#include<bits/stdc++.h>
using namespace std;
#define ljl long long
const ljl N=1005,M=1e5+5;
ljl n,m,k,cnt_e,u,v,head[N],pl[N],fa[N],cnt_node[N],maxn,ans,num;
bool pol[N],vis[N];
//突然发现建边貌似并没有用,可以忽略建边的一系列操作。
struct E{
	ljl to,pre;
}e[M<<1];
void add(ljl from,ljl to)
{
	e[++cnt_e].to=to;
	e[cnt_e].pre=head[from];
	head[from]=cnt_e;
	return;
}
//并查集模板--------------------
ljl findfa(ljl x)
{
	return fa[x]==x?x:fa[x]=findfa(fa[x]);
}
void Union(ljl x,ljl y)
{
	fa[findfa(x)]=findfa(y);
	return;
}
//并查集模板--------------------
ljl getnum(ljl x)//公式
{
	return x*(x-1)/2;
}
int main(){
    //浅浅关个同步流
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m>>k;
	for(ljl i=1;i<=n;++i)
		fa[i]=i;//并查集的初始化
	for(ljl i=1;i<=k;++i)
	{
		cin>>pl[i];
		pol[pl[i]]=true;//标记此乃特殊点
	}
	for(ljl i=1;i<=m;++i)
	{
		cin>>u>>v;
		add(u,v);add(v,u);
		Union(u,v);//并查集的合并
	}
	for(ljl i=1;i<=n;++i)
	{
		++cnt_node[findfa(i)];//统计每个连通块内成员个数
		pol[findfa(i)] |= pol[i];//若当前节点是特殊点,那么这个连通块肯定也是
	}
	for(ljl i=1;i<=n;++i)
	{
		ljl fx=findfa(i);
		if(vis[fx]) continue;
		vis[fx]=1;
        //开始实施答案统计
		if(pol[fx])
		{
			if(cnt_node[fx]<=maxn)
				ans+=getnum(cnt_node[fx]);
			else
			{
				ans+=getnum(maxn);
				maxn=cnt_node[fx];
			}
		}
		else
			num+=cnt_node[fx];
	}
	ans+=getnum(maxn+num);
	cout<<ans-m<<'\n';
	return 0;
}

AC 记录

标签:连通,特殊,Hongcow,Builds,题解,合并,ljl,maxn,个点
From: https://www.cnblogs.com/Atserckcn/p/18613525

相关文章

  • P6803 [CEOI2020] 星际迷航 题解
    \(\text{P6803[CEOI2020]星际迷航题解}\)观察这个从第\(0\)棵树走向第\(D\)棵树的过程是困难的,我们难以判定走到下一棵树的情况。于是我们不妨从第\(D\)棵树向第\(0\)棵树来倒推。从第\(i\)层走向第\(i+1\)层的边为\(x\toy\)时,事实上此时\(y\)就是第\(i+1\)......
  • CF335F 题解
    \(CF335F\)\(Buy\)\(One\),\(Get\)\(One\)\(Free\)考虑可撤销贪心+小根堆维护。首先价格相同的馅饼可以放到一起考虑,从大到小排序后考虑每种不同价格的馅饼。则第\(i\)种最多白嫖的个数为\(p=\min(c_i,num-2*sum)\),其中\(c_i\)为馅饼个数,\(num\)为已经考虑的更贵的......
  • 7 Oracle 经典面试题解析
    PL/SQL面试题--1、创建序列seq_employee,该序列每次取的时候自动增加,从1开始计数,不设最大值,并且一直累加,不循环;CREATESEQUENCEseq_employeeSTARTWITH1INCREMENTBY1NOMAXVALUE;--也可以直接使用简单默认参数:--CREATESEQUENCEseq_employee;SELECTseq_employee.NEXTV......
  • 题解:牛客周赛 Round 72(A-D)(E只有代码)
    先附上补题链接,没打的同学可以来补一下:https://ac.nowcoder.com/acm/contest/98256A小红的01串(一)题意找到一个01串中相邻字符不同的对数做法从头到尾扫一遍,计算前后不一样的字符就可以了#include<bits/stdc++.h>signedmain(){std::ios::sync_with_stdio(false)......
  • 题解:AT_abc266_c [ABC266C] Convex Quadrilateral
    思路对于一个凸多边形,它的任意内角一定小于\(45\degree\)。如果每相邻两条边的叉积的符号相同就说明它们是顺时针或逆时针排列的,则可以判别出该四边形是否为凸四边形。AC代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;intX1,X2,X3,X4,Y1,Y2,Y3......
  • 题解:AT_abc296_e [ABC296E] Transition Game
    题目传送门思路我们可以在环中任选一点,然后在环内可以转到另一个点。因为起点自由选择,所以环中每个点都可以到达,由此我们可以得知环上的所有点都是必胜点。我们把这个问题抽象为一张图,用拓扑排序判环即可。AC代码#include<bits/stdc++.h>usingnamespacestd;usingll=l......
  • 题解:B3832 [NICA #2] 回来吧我的小波
    思路经典抽屉原理。对于长度大于\(9\)的子串,我们就可以认为它一定是好的,因为一定有两个数是相同的,它们可以互相整除。对于剩下长度小于等于\(9\)的子串,我们对它们进行暴力枚举即可。AC代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;strings......
  • 题解:B3803 [NICA #1] 上大分
    思路看到这道题首先考虑贪心和动态规划。贪心是不行的,因为这里有先减分再加分的数据,也就是说故意在div1的比赛掉分,使得下一次能够打div2加更多的分。我们考虑动态规划,我们用\(f[i][j]\)表示在前\(i\)场比赛中得\(j\)分至少需要打几场比赛,就可以轻易推出这题的转移方......
  • 题解:AT_abc236_f [ABC236F] Spices
    今天2024秋令营Day1的贪心例题,来解释一下这道题贪心的思路。首先输入一个整数\(n\),表示需要处理的数字数量为\(2^n-1\),随后输入每个编号的代价,并将代价和编号存储在数组\(a\)中。接着,对代价进行排序,以便在后续处理中优先选择代价较小的数字。然后,使用一个\(vis\)数......
  • 题解:P7020 [NWRRC2017] Boolean Satisfiability
    首先,我们需要明确一个重要的恒等式:\[x\mid\nega=1\]当\(x=1\)时,\(x\mid\negx=1\mid0\)的结果为\(1\)。当\(x=0\)时,\(x\mid\negx=0\mid1\)的结果同样为\(1\)。因此,我们可以得出结论,该式子的结果恒为\(1\)。接下来,我们观察到,当表达式中仅包含......