P6279 题解

P6279 题解

Overview

结论(待论证)

Description

给定一个有向图,这个有向图的每一个点所连接的点属于同一个集合。

求集合数量最大且字典序最小的集合标号方案。

Solution

先讲结论。

结论 :用 vector 存储每个点所连接的点,从 1 1 1 到 n n n 暴力用并查集按秩 合并(要合并 vector 的东西,一层一层的合并下去)。

Proof

先讲复杂度。

时间复杂度 O ( α ( n ) ) O(\alpha (n)) O(α(n))。

按秩合并空间复杂度 O ( n ) O(n) O(n),vector 的存储的东西的空间被 clear 了,(其实我也不清楚 clear 的原理)所以没事。

再讲正确性。

这里,合并一定会合并到底。

Code

cpp 复制代码
#include <bits/stdc++.h>
#define int long long

using namespace std;

int fa[200001], sz[200001];
vector<int> vec[200001];

int FindFather(int x){
	if(fa[x] == x) return x;
	int tmp = FindFather(fa[x]);
	sz[x] = sz[fa[x]] + 1;
	return fa[x] = tmp;
}
void Union(int u, int v){
	u = FindFather(u), v = FindFather(v);
	if(u == v) return;
	if(sz[u] < sz[v]) swap(u, v);
	sz[u] += sz[v];
	fa[v] = u;
	for(int i = 0; i < vec[v].size(); i++)
		if(vec[u].size()) Union(vec[u][0], vec[v][i]);
	for(int i = 0; i < vec[v].size(); i++)
		vec[u].push_back(vec[v][i]);
}

signed main(){
	int n, m; cin >> n >> m;
	for(int i = 1; i <= n; i++) fa[i] = i;
	for(int i = 1; i <= m; i++){
		int u, v; cin >> u >> v;
		vec[u].push_back(v);
	}
	for(int i = 1; i <= n; i++){
		if(vec[i].size() > 1){
			for(int j = 0; j < vec[i].size() - 1; j++){
				Union(vec[i][j], vec[i][j + 1]);
			}
		}
	}
	map<int, int> mp;
	int tot = 0;
	for(int i = 1; i <= n; i++){
		if(!mp[FindFather(i)]) mp[fa[i]] = ++tot;
		cout << mp[fa[i]] << endl;
	}
	return 0;
}
相关推荐
sunburn-14 分钟前
Java堆(Heap)详解与实战教学
java·开发语言·数据结构·ide·算法
jayson.h29 分钟前
PDF 合并+添加页码 相关库、类、函数
开发语言·前端·python
qq_3227627538 分钟前
一个接口从能用到稳定,中间差的到底是什么
服务器·开发语言·lua·接口·fastapi·请求
Data_Journal1 小时前
Scrapyd:分步教程
开发语言·python·microsoft·golang·编辑器·html·iphone
智碳能碳管理平台1 小时前
工业能耗台账标准化:能碳管理系统的数据口径怎么设计
算法·能碳管理系统·智碳能碳管理平台·企业能碳管理系统·碳排放核算软件·绿色工厂申报saas·能碳管理平台
带多刺的玫瑰1 小时前
Leecode#15刷题之三数之和
算法·leetcode·职场和发展
离陌在学C#2 小时前
C# 异步编程:从 async/await 到 Task 实战指南
开发语言·数据库·c#
羚尔2 小时前
C语言数组
c语言·开发语言
哭泣方源炼蛊2 小时前
并查集进阶 P1(带权并查集,并查集分类)
数据结构·c++·算法·二进制·带权并查集
牧羊人.3332 小时前
动手学深度学习 02 | 手写数字识别
图像处理·人工智能·深度学习·算法