upc 连通块

时间限制: 1 Sec 内存限制: 128 MB

题目描述

Smart终于忙玩了各种各样的课程,终于可以继续学习算法了。
他在图论书上看到了树,树有许许多多特殊的性质。Smart一下子就喜欢上了这种特殊的树。于是,他发明了自己对于无向图的评分方法。一个无向图的分数定义为:各个连通块是树的数量。现在给定一个n个点m条边的无向图,问在Smart的评分方法下,分数为多少。
一个连通块是树,当且仅当边数比点数少1。

输入

第一行两个整数n和m,表示图的点数和边数。
第二行有m对整数,u和v表示,结点u和节点v之间有边。给出的无向图不存在重边。

输出

输出一行包括一个整数,表示无向图的评分,也就是树的数量。

样例输入
8 6
1 2
2 4
1 3
5 6
6 7
5 7
样例输出
2
提示

样例解释
在这里插入图片描述
图中第 1 个和第 3 个连通块是树。
【数据范围】
20%的数据:1≤n≤2000;
100%的数据:1≤n≤100000,0≤m≤min(n*(n-1)/2,200000)。

思路

题目是要求树的数目;
而树满足:边数 = 点数 - 1;
所以我们知道图的边数和点数便知道这个图是不是树
我们在连通图的时候同时记录图的边数和点数
将边和点都加在根节点上,最后直接判断根节点的边数和点数即可
详细过程请看代码

代码:

#include<iostream>
#include<string>
#include<map>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
const double eps=1e-6;
const int N=1e5+10;
const int maxn=2e9;
const int mod=1e9+7;
int n,m,ans,pre[N];
int dian[N],bian[N];
int find(int x)
{
    if(x==pre[x]) return x;
    else return pre[x]=find(pre[x]);
}
void unions(int a,int b)
{
    int fa=find(a);
    int fb=find(b);
    if(fa==fb) bian[fa]++;//根节点的边数 + 1
    else
    {
        pre[fb]=fa;
        bian[fa]+=bian[fb]+1;//边和点都加在根节点上,最后直接判断根节点即可
        dian[fa]+=dian[fb];
    }
    return ;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<=n;i++) 
    {
        pre[i]=i;
        dian[i]=1;//初始化每个点的点数都是1
    }
    for(int i=0;i<m;i++)
    {
        int a,b;
        cin>>a>>b;
        unions(a,b);
    }
    for(int i=1;i<=n;i++)
    {
        if(pre[i]==i)//判断是否为根节点
        {
            if(bian[i]==dian[i]-1) ans++;
        }
    }
    cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值