Trees
时间限制:1000 ms | 内存限制:65535 KB
难度:2
-
描述
-
A graph consists of a set vertices and edges between pairs of vertices. Two vertices are connected if there is a path(subset of edges)leading from one vertex to another, and a connected component is a maximal subset of vertices that are all connected to each other. A graph consists one or more connected components.A tree is a connected component without cycles, but it can also be characterized in other ways. For example, a tree consisting of n vertices has exactly n-1 edges.Also, there is a unique path connecting any pair of vertices in a tree.Give a graph, report the number of connected components that are also trees.
-
输入
- The input consist of a number of cases. Each case starts with two non-negative integer n and m, satisfying n <= 500 and m <= n(n-1)/2. This is followed by m lines,each containing two integers specifying the two vertices connected by an edge. The vertices are labeled from 1 to n. The end of input is indicated by a line containing n = m = 0. 输出
- For each case,print one of the following lines depending on how
many different connected components are trees.(T > 1 below):
Case x: A forest of T trees.
Case x: There is one tree.
Case x: No Trees.
x is the case number (starting from 1).
样例输入 -
6 3 1 2 2 3 3 4 6 5 1 2 2 3 3 4 4 5 5 6 6 6 1 2 2 3 1 3 4 5 5 6 6 4 0 0
样例输出 -
Case 1: A forest of 3 trees. Case 2: There is one tree. Case 3: No Trees.
题意:给出一张由n个点和m条边构成的无向图,不是连通的,判断图的每一部分是否是一个树,即图中有几棵树。
满足下列条件可以的点和边可以构成一棵树:1.n个点由n-1条边相连,任意两个点之间只有一条边相连。
解题思路:用并查集把各个部分找出来,对于每一部分判断所有点的度之和与点个数的关系,
如果度之和等于点数*2-2,则可以构成一棵树。
#include<cstdio> #include<algorithm> #include<vector> using namespace std; const int N = 5e2 + 10; int father[N], deg[N]; vector<int> vec[N]; void Initial(int n) //初始化 { for(int i = 1; i <= n; i++) father[i] = i, deg[i] = 0; } int Find(int x) //寻找父节点 { if(father[x] != x) father[x] = Find(father[x]); return father[x]; } void Union(int a, int b) //合并两个集合 { int p = Find(a); int q = Find(b); if(p != q) father[p] = q; } int main() { int n, m, i, j, cas = 1; while(~scanf("%d%d",&n,&m) && (n+m)) { Initial(n); //并查集初始化 int u, v; for(i = 0; i < m; i++) { scanf("%d%d",&u,&v); deg[u]++; deg[v]++; Union(u,v); } //求每个点的度数 for(i = 1; i <= n; i++) { vec[i].clear();//删除容器中保存的所有元素 if(Find(i) == i) { for(j = 1; j <= n; j++) { if(Find(j) == Find(i)) vec[i].push_back(j); } } }//找出哪些点属于同一个集合 int ans = 0; for(i = 1; i <= n; i++) { int cnt = vec[i].size(); if(cnt == 0) continue; int sum = 0; for(j = 0; j < cnt; j++) { sum += deg[vec[i][j]]; }//求集合中点的度数之和 if(sum == cnt * 2 - 2) ans++; //图中无环 } printf("Case %d: ",cas++); if(ans == 0) printf("No Trees.\n"); else if(ans == 1) printf("There is one tree.\n"); else printf("A forest of %d trees.\n",ans); } return 0; }