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
提示

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

思路

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

代码:

#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#define X first
#define Y second
#define INF 0x3f3f3f3f
#define P pair
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;
}

你可能感兴趣的:(并查集)