并查集+巧妙分块,Codeforces1424B. 0-1 MST

目录

一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

二、解题报告

1、思路分析

2、复杂度

3、代码详解


一、题目

1、题目描述

Ujan has a lot of useless stuff in his drawers, a considerable part of which are his math notebooks: it is time to sort them out. This time he found an old dusty graph theory notebook with a description of a graph.

It is an undirected weighted graph on n vertices. It is a complete graph: each pair of vertices is connected by an edge. The weight of each edge is either 0 or 1; exactly mm edges have weight 1, and all others have weight 0.

Since Ujan doesn't really want to organize his notes, he decided to find the weight of the minimum spanning tree of the graph. (The weight of a spanning tree is the sum of all its edges.) Can you find the answer for Ujan so he stops procrastinating?

2、输入输出

2.1输入

The first line of the input contains two integers n and m (1≤n≤10^5, 0≤m≤min(n*(n−1)/2,10^5)), the number of vertices and the number of edges of weight 1 in the graph.

The i-th of the next m lines contains two integers ai and bi (1≤ai,bi≤n, ai≠bi), the endpoints of the i-th edge of weight 1.

It is guaranteed that no edge appears twice in the input.

2.2输出

Output a single integer, the weight of the minimum spanning tree of the graph.

3、原题链接

Problem - 1242B - Codeforces (Unofficial mirror by Menci)


二、解题报告

1、思路分析

思来想去只能想到O(n^2)解法,看到大佬一句话点破梦中人了属于是orz。

朴素思想:直接跑生成树------MLE

进一步:无权边连通块数目-1即为答案------如果只能想出O(n^2)解法会TLE

一个特别妙的思路:因为一共有m条带权边,那么只考虑带权边的情况下所有节点的出度入度之和为2*m,那么假如最小度为dmin,那么度为dmin的点不会超过2*m/n!!!(这个不难想

精彩的来了:我们先拿到一个最小度的点,O(n)求出它所在的无权边连通块,那么剩下的点中的无权边连通块的数目即为答案

那么如何求剩下点的无权连通块呢?

剩下的点不超过2*m/n个,我们对于每个点都枚举1~n的所有点,如果两个点之间没有边就合并

这一步骤时间复杂度为O(2*m/n * n) = O(m)!!!

所以我们在O(N+M)的时间内就解决了问题

最坏情况下,如果最小度的点特别多,我们效率仍然是线性的(可以结合n,m的数据范围想一下

2、复杂度

时间复杂度:O(n+m) 空间复杂度:O(m)

3、代码详解

复制代码
cpp 复制代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
const int M = 505;
int n, m, cnt;
bool g[M][N];
struct edge
{
    int u, v;
} edges[N];
int deg[N], minid = 0;
int p[N];
int seq[N], tot = 0, pos[N];
int findp(int x)
{
    return p[x] < 0 ? x : p[x] = findp(p[x]);
}
bool Union(int x, int y)
{
    int px = findp(x), py = findp(y);
    if (px == py)
        return false;
    if (p[px] > p[py])
        swap(px, py);
    p[px] += p[py], p[py] = px;
    return true;
}
bool vis[N];
int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    // freopen("in.txt", "r", stdin);
    cin >> n >> m, memset(p, -1, sizeof(p));
    for (int i = 1, u, v; i <= m; ++i)
        cin >> u >> v, edges[i] = {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 <= m; ++i)
    {
        if (edges[i].u == minid)
            vis[edges[i].v] = true;
        if (edges[i].v == minid)
            vis[edges[i].u] = true;
    }
    for (int i = 1; i <= n; ++i)
        if (vis[i])
            seq[++tot] = i, pos[i] = tot;
        else
            Union(i, minid);

    for (int i = 1; i <= m; ++i)
    {
        if (vis[edges[i].u])
            g[pos[edges[i].u]][edges[i].v] = true;
        if (vis[edges[i].v])
            g[pos[edges[i].v]][edges[i].u] = true;
    }
    for (int i = 1; i <= tot; ++i)
        for (int j = 1, u = seq[i]; j <= n; ++j)
            if (g[i][j])
                continue;
            else
                cnt += Union(u, j);

    cout << tot - cnt;
    return 0;
}
相关推荐
天上飞的粉红小猪5 分钟前
c++的IO流
开发语言·c++
ygklwyf14 分钟前
JPRS编程竞赛2026#1(AtCoder初学者竞赛442)
c++·算法·模拟
王老师青少年编程15 分钟前
信奥赛C++提高组csp-s之倍增算法思想及应用(3)
c++·noip·csp·信奥赛·csp-s·提高组·倍增算法
学嵌入式的小杨同学20 分钟前
【嵌入式 Linux 实战 1】Ubuntu 环境搭建 + 目录结构详解:嵌入式开发入门第一步
linux·c语言·开发语言·数据结构·vscode·vim·unix
老鼠只爱大米24 分钟前
LeetCode经典算法面试题 #21:合并两个有序链表(迭代法、原地合并法等多种实现方案详解)
算法·leetcode·链表·优先队列·迭代法·合并两个有序链表·原地合并
源代码•宸25 分钟前
Leetcode—47. 全排列 II【中等】
经验分享·后端·算法·leetcode·面试·golang·深度优先
wen__xvn27 分钟前
基础算法集训第20天:Dijkstra
算法·图论
Ada's37 分钟前
【计算机基础系列】001:计算机科学与技术
数据结构
万象.43 分钟前
redis客户端安装与实现C++版本
数据库·c++·redis
Yiyaoshujuku1 小时前
疾病的发病率、发病人数、患病率、患病人数、死亡率、死亡人数查询网站及数据库
数据库·人工智能·算法