NYOJ 920 Trees

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;
}


你可能感兴趣的:(NYOJ 920 Trees)