AtCoder Beginner Contest 229 E 并查集 逆向思维建边

43 篇文章 1 订阅
该博客讨论了一个图论问题,涉及完全图中点的删除如何影响连通图的数量。作者从结果出发,采用逆向思维,逐步构建从小到大的边,并使用并查集来跟踪连通分量。在每删除一个点时更新连通图的数量,并给出了AC代码实现。
摘要由CSDN通过智能技术生成

题目

给你N点M边的完全图,每次按点的编号不断删除点(从1到n)。
问你每次删除后有几个连通图。

题解思路

不妨从结果往前考虑。
最终状态肯定是一个点都没有,0个连通图。

我们从N往前加边加点。然后将可以连接的点并查起来即可。
这样我们只需建小到大的单项边即可。
大到小的时候,小的点被删除了。

AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long

using namespace std;

const  int  INF =  0x3f3f3f3f;
int n , m ;
vector <int> head[200100] ; 
int a[200100] ; 
int vis[200100] ; 

int find(int x )
{
    if ( x != a[x] )
        return a[x] = find(a[x]) ; 
    return a[x] ;
}
int  uio (int x , int y )
{
    int fx = find(x) ;
    int fy = find(y) ;
    if ( fx != fy )
    {
        a[fy] = fx ; 
        return 1 ;
    }
    return 0 ;
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin >> n >> m ;
    for (int i = 1 ; i <= m ; i++ )
    {
        int t1 , t2 ;
        cin >> t1 >> t2 ;
        if ( t1 > t2 )
            swap(t1,t2);
        head[t1].push_back(t2) ;
    }
    for (int i = 1 ; i <= n ; i++ )
        a[i] = i ;
    int qs = 0 ;
    vector <int> ans ;
    ans.push_back(0) ; 
    for (int i = n ; i > 1 ; i-- )
    {
        qs++;
        for (int j = 0 ; j < head[i].size() ; j++ )
        {
            int sp = head[i][j] ; 
            qs -= uio(i,sp);
        }
        ans.push_back(qs);
    }

    reverse(ans.begin(),ans.end());

    for ( auto i : ans )
        cout << i << "\n" ; 

    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值