问题 C: NH树
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
小明终于忙玩了各种各样的课程,终于可以继续学习算法了。
他在图论书上看到了树,树有许许多多特殊的性质。小明一下子就喜欢上了这种特殊的树。
于是,他发明了自己的对于无向图的评分方法。
一个无向图的分数定义为,各个连通块是树的数量。
现在给定一个 n 个点 m 条边的无向图,问在小明的评分方法下,分数为多少。
一个连通块是树,当且仅当边数比点数少 1。
输入
第一行两个整数 n 和 m,表示图的点数和边数。
第二行有 m 对整数,u 和 v 表示,结点 u 和节点 v 之间有边。
给出的无向图不存在重边。
输出
输出一行包括一个整数,表示无向图的评分,也就是树的数量。
样例输入 Copy
8 6
1 2
1 3
2 4
5 6
6 7
5 7
样例输出 Copy
2
提示
20%的数据,1<=n<=2000
100%的数据,1<=n<=100000,0<=m<=min(n*(n-1)/2,200000)
#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
const int M = 100005;
vector<int>v[M];
int n,m;
bool vis[M],flag;
void dfs(int x,int last){
vis[x] = 1;
for(int i=0; i<v[x].size(); i++){
if(vis[v[x][i]]){
if(v[x][i]!=last)
flag = true; // 我们就认为连通图中存在环,不是树
}
else
dfs(v[x][i],x);
}
}
int main()
{
cin >> n >> m;
int x,y;
while(m--){
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
int ans = 0;
for(int i=1; i<=n; i++){
if(!vis[i]){
flag = false;
dfs(i,-1);
if(!flag)
ans++;
}
}
cout << ans << endl;
return 0;
}