ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CF1242B]0-1 MST 题解

2022-01-25 23:32:58  阅读:169  来源: 互联网

标签:pre CF1242B int 题解 MST maxn include operatorname 暴力


CF1242B 0-1 MST

传送门

  • 思路:

(注:此文设题中输入的图为 \(G_1\),对应的完全图为 \(G_2\),对应的补图为 \(G_3\))

首先不难想到暴力思路:直接将 \(G_2\) 建出来,跑一遍 MST 即可。

然而这样时间和空间复杂度都是 \(\operatorname{O}(N^2)\) 的,显然无法承受。

但是这道题显然有别的思路,考虑从特殊的边长:\(0\) 和 \(1\) 入手。

题中所给的边长为 \(1\) 的边视为断边,建出 \(G_3\),不难发现,答案就是补图的连通块数量减 \(1\)。

我们只需要算出连通块的数量即可,可以用并查集处理。

然而边数仍然很多,直接暴力求连通块很容易 TLE/MLE。

这时这个题目巧妙的地方就来了:我们可以将求解拆成两块,再合并答案。

首先发现,在原图 \(G_1\) 中,设点 \(i\) 的度数为 \(deg_i\),不难发现

\[\sum\limits_{i=1}^n deg_i =2m \]

那么根据抽屉原理,其中度数最小的点度数不超过 \(\frac{2m}{n}\) ,设该点为 \(u\) .

则可以先将 \(G_1\) 中与 \(u\) 没有连边的点和 \(u\) 暴力合并,和 \(u\) 有连边的点存储下来,暴力合并。

其中暴力合并的复杂度为 \(\operatorname{O}(N)\),则整体的时间复杂度为 \(\operatorname{O}(N+N\times \frac{2m}{N})=\operatorname{O}(N+M)\).

code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100005;
const int maxm = 505;
int n,m;
int cnt;
bool g[maxm][maxn];
struct Edge {
	int u,v;
	Edge() {
		u = v = 0;
	}
	Edge(int u,int v):u(u),v(v){}
}E[maxn];
int deg[maxn],minid = 0;
int pre[maxn];
int seq[maxn],tot = 0,pos[maxn];
int find(int x) {
	return x == pre[x] ? x : pre[x] = find(pre[x]);
}
bool vis[maxn];
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= m;++ i) {
		int u,v;
		scanf("%d%d",&u,&v);
		E[i] = Edge(u , v);
		++ deg[u];
		++ deg[v];
	}
	minid = 1;
	for(int i = 2;i <= n;++ i)
		if(deg[i] < deg[minid])minid = i;
	for(int i = 1;i <= n;++ i)pre[i] = i;
	for(int i = 1;i <= m;++ i) {
		if(E[i].u == minid)vis[E[i].v] = true;
		if(E[i].v == minid)vis[E[i].u] = true;
	}
	for(int i = 1;i <= n;++ i) {
		if(vis[i])++ tot,seq[tot] = i,pos[i] = tot;
		else pre[i] = minid;
	}
	//Merge part
	for(int i = 1;i <= m;++ i) {
		if(vis[E[i].u])g[pos[E[i].u]][E[i].v] = true;
		if(vis[E[i].v])g[pos[E[i].v]][E[i].u] = true;
	}
	for(int i = 1;i <= tot;++ i) {
		int u = seq[i];
		for(int j = 1;j <= n;++ j) {
			if(g[i][j])continue ;
			int r1 = find(u),r2 = find(j);
			if(r1 == r2)continue ;
			pre[r1] = r2;
			++ cnt;
		}
	}
	printf("%d",tot - cnt);
	return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

标签:pre,CF1242B,int,题解,MST,maxn,include,operatorname,暴力
来源: https://www.cnblogs.com/663B/p/15845027.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有